$30 off During Our Annual Pro Sale. View Details »

Что нового в Fragment 1.4

Что нового в Fragment 1.4

Видео версия https://youtu.be/UWuuqbNIWpE

Крайний релиз Jetpack Fragment вышел очень интересным на фичи, что заслужил озвучить изменения в отдельном видео, а именно:
🔥 Новый менеджер состояний
🔥 Несколько back stack
🔥 FragmentStrictMode
💪 Новые проверки кода в Android Lint
🚀 Улучшение работы анимаций
🔨 Исправление багов в работе ЖЦ Fragment

Kirill Rozov

December 12, 2021
Tweet

More Decks by Kirill Rozov

Other Decks in Programming

Transcript

  1. Fragment 1.4
    Кирилл Розов, Android Broadcast, декабрь 2021
    Как похорошели Fragment

    View Slide

  2. FragmentContainer.getFragment

    View Slide

  3. android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="dev.androidbroadcast.fragmentdemo.FirstFragment"
    android:tag="first"
    !"

    View Slide

  4. android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="dev.androidbroadcast.fragmentdemo.FirstFragment"
    android:tag="first"
    !"

    View Slide

  5. val fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
    val homeFragment: HomeFragment = fragment as HomeFragment

    View Slide

  6. val fragmentContainer: FragmentContainerView = …
    val homeFragment: HomeFragment = fragmentContainer.getFragment()

    View Slide

  7. Новый менеджер состояний
    теперь единственный

    View Slide

  8. Что изменили
    ! Исправили множество багов с навигацией

    ! Управление состоянием Fragment

    ! Заложена поддержка для множественного back stack

    ! Упрощение жизненного цикла Fragment [результатов пока не видно]

    View Slide

  9. View Slide

  10. View Slide

  11. FragmentStrictMode

    View Slide

  12. supportFragmentManager.strictModePolicy =
    FragmentStrictMode.Policy.Builder()
    .penaltyDeath()
    .penaltyListener(…)
    .penaltyLog()
    .detectFragmentReuse()
    .detectFragmentTagUsage()
    .detectRetainInstanceUsage()
    .detectTargetFragmentUsage()
    .detectWrongFragmentContainer()
    .detectSetUserVisibleHint()
    .build()

    View Slide

  13. supportFragmentManager.strictModePolicy =
    FragmentStrictMode.Policy.Builder()
    .penaltyDeath()
    .penaltyListener(…)
    .penaltyLog()
    .detectFragmentReuse()
    .detectFragmentTagUsage()
    .detectRetainInstanceUsage()
    .detectTargetFragmentUsage()
    .detectWrongFragmentContainer()
    .detectSetUserVisibleHint()
    .build()

    View Slide

  14. penaltyDeath
    2021-12-11 17:08:56.170 12010-12010/dev.androidbroadcast.fragmentdemo E/FragmentStrictMode: Policy
    violation with PENALTY_DEATH in dev.androidbroadcast.fragmentdemo.FirstFragment
    androidx.fragment.app.strictmode.SetUserVisibleHintViolation: Attempting to set user visible hint
    to true for fragment FirstFragment{300fd8d} (9fbf6047-2ed5-4952-b7bd-4d513035c141 id=0x7f0800c5)
    at
    androidx.fragment.app.strictmode.FragmentStrictMode.onSetUserVisibleHint(FragmentStrictMode.kt:131)
    at androidx.fragment.app.Fragment.setUserVisibleHint(Fragment.java:1335)
    at dev.androidbroadcast.fragmentdemo.FirstFragment.onViewCreated(FirstFragment.kt:26)
    at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3019)
    at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
    at
    androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
    at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
    at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2777)
    at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3020)
    at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
    at
    androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
    at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
    at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2784)
    at
    androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:262)
    at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:478)
    at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)

    View Slide

  15. penaltyLog
    2021-12-11 17:10:19.516 12163-12163/dev.androidbroadcast.fragmentdemo D/FragmentStrictMode: Policy violation in
    dev.androidbroadcast.fragmentdemo.FirstFragment
    androidx.fragment.app.strictmode.SetUserVisibleHintViolation: Attempting to set user visible hint to true for fragment
    FirstFragment{300fd8d} (e2010f02-eb83-416b-a7ac-05aaa3befd12 id=0x7f0800c5)
    at androidx.fragment.app.strictmode.FragmentStrictMode.onSetUserVisibleHint(FragmentStrictMode.kt:131)
    at androidx.fragment.app.Fragment.setUserVisibleHint(Fragment.java:1335)
    at dev.androidbroadcast.fragmentdemo.FirstFragment.onViewCreated(FirstFragment.kt:26)
    at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3019)
    at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
    at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
    at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2777)
    at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3020)
    at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
    at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
    at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2784)
    at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:262)
    at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:478)
    at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)

    View Slide

  16. penaltyListener
    FragmentStrictMode.Policy.Builder()
    .penaltyListener() { vialotation: Violation !"
    }

    View Slide

  17. penaltyListener
    FragmentStrictMode.Policy.Builder()
    .penaltyListener() { vialotation: Violation !"
    }
    Firebase.crashlytics.recordException(vialotation)

    View Slide

  18. supportFragmentManager.strictModePolicy =
    FragmentStrictMode.Policy.Builder()
    .penaltyDeath()
    .penaltyListener(…)
    .penaltyLog()
    .detectFragmentReuse()
    .detectFragmentTagUsage()
    .detectRetainInstanceUsage()
    .detectTargetFragmentUsage()
    .detectWrongFragmentContainer()
    .detectSetUserVisibleHint()
    .build()

    View Slide

  19. detectFragmentReuse
    !" Повторное использование Fragment, который был удален из FragmentManager
    val firstFragment =
    fragmentManager.findFragmentByTag(FRAGMENT_TAG_FIRST) !7 return
    fragmentManager.commit {
    remove(firstFragment)
    }
    fragmentManager.commit {
    !" Добавление Fragment, удалённого ранее
    add(R.id.fragment_container, firstFragment, FRAGMENT_TAG_FIRST)
    }

    View Slide

  20. detectFragmentTagUsage
    !" Использование тэга при добавление Fragment в XML
    android:name="dev.androidbroadcast.fragmentdemo.FirstFragment"
    android:tag="first"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    !"

    View Slide

  21. detectWrongFragmentContainer
    !" Неправильный layout-контейнер для Fragment
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="dev.androidbroadcast.fragmentdemo.FirstFragment"
    android:tag="first"
    !"

    View Slide

  22. detectWrongFragmentContainer
    !# Правильный layout-контейнер для Fragment
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="dev.androidbroadcast.fragmentdemo.FirstFragment"
    android:tag="first"
    !"

    View Slide

  23. detectSetUserVisibleHint
    !" userVisibleHint уже deprecated
    fragment.userVisibleHint = false

    View Slide

  24. detectRetainInstanceUsage
    !" retainInstance уже deprecated
    fragment.retainInstance = true
    if (fragment.retainInstance) {
    !!@
    }

    View Slide

  25. detectTargetFragmentUsage
    !" setTargetFragment уже deprecated
    firstFragment.setTargetFragment(secondFragment, FRAGMENT_REEQUEST_CODE)

    View Slide

  26. Fragment Result API
    class FirstFragment : Fragment() {
    parentFragmentManager.setFragmentResultListener(
    FRAGMENT_REQUEST_KEY,
    viewLifecycleOwner
    ) { requestKey: String, result: Bundle !"
    }
    }

    View Slide

  27. Множественный Back Stack

    View Slide

  28. Добавление Fragment в Back Stack
    Back Stack

    View Slide

  29. Добавление Fragment в Back Stack
    supportFragmentManager.commit {
    replace(
    R.id.fragment_container,
    homeFragment,
    FRAGMENT_TAG_HOME
    )
    addToBackStack(null)
    }
    Back Stack
    HomeFragment

    View Slide

  30. SavedState
    Back Stack

    View Slide

  31. !" Добавляем начальный Fragment
    supportFragmentManager.commit {
    setReorderingAllowed(true)
    replace(R.id.fragment_container)
    }
    SavedState
    Back Stack
    HomeFragment

    View Slide

  32. SavedState
    Back Stack
    HomeFragment

    View Slide

  33. supportFragmentManager.commit {
    setReorderingAllowed(true)
    replace(R.id.fragment_container)
    addToBackStack("profile")
    }
    SavedState
    Back Stack
    HomeFragment
    ProZleFragment
    EditProZleFragment
    supportFragmentManager.commit {
    setReorderingAllowed(true)
    replace(R.id.fragment_container)
    addToBackStack("profile")
    }

    View Slide

  34. SavedState
    Back Stack
    HomeFragment
    ProZleFragment
    EditProZleFragment

    View Slide

  35. SavedState
    proZle
    Back Stack
    HomeFragment
    ProZleFragment
    EditProZleFragment
    supportFragmentManager.saveBackStack("profile")

    View Slide

  36. NotiZcationsFragment
    SavedState
    proZle
    Back Stack
    HomeFragment
    ProZleFragment
    EditProZleFragment
    supportFragmentManager.saveBackStack("profile")
    supportFragmentManager.commit {
    setReorderingAllowed(true)
    replace(R.id.fragment_container)
    addToBackStack("notifications")
    }

    View Slide

  37. SavedState
    proZle
    Back Stack
    HomeFragment
    ProZleFragment
    EditProZleFragment
    NotiZcationsFragment

    View Slide

  38. SavedState
    proZle
    supportFragmentManager.saveBackStack("notifications")
    Back Stack
    HomeFragment
    ProZleFragment
    EditProZleFragment
    notiZcations
    NotiZcationsFragment

    View Slide

  39. SavedState
    supportFragmentManager.saveBackStack("notifications")
    Back Stack
    HomeFragment
    ProZleFragment
    EditProZleFragment
    notiZcations
    NotiZcationsFragment
    supportFragmentManager.restoreBackStack("profile")

    View Slide

  40. SavedState
    Back Stack
    HomeFragment
    ProZleFragment
    EditProZleFragment
    notiZcations
    NotiZcationsFragment

    View Slide

  41. SavedState
    supportFragmentManager.clearBackStack("notifications")
    Back Stack
    HomeFragment
    ProZleFragment
    EditProZleFragment

    View Slide

  42. View Slide

  43. Новые Android Lint проверки

    View Slide

  44. Новые проверки в Android Lint
    ! UseGetLayoutInflater
    Использование неправильного LayoutInflater в DialogFragment
    ! DialogFragmentCallbacksDetector
    Переопределение callback у Dialog, а не DialogFragment
    ! FragmentAddMenuProvider
    Использование неверного Lifecycle при использовании addMenuProvider
    ! DetachAndAttachFragmentInSameFragmentTransaction
    Выполнение attach и detach для одного и того же Fragment в рамках одной транзакции

    View Slide