Multi Back Stack, StrictMode


If you are interested in Android development, you have most likely heard of Telegram channel “Android Broadcast” with daily news for Android developers and eponymous YouTube channel… This post is text version video

One of the biggest Android Jetpack updates in recent memory came out quite recently. As part of it, many libraries entered a new stable phase, but the most interesting release in this update, I think, is version 1.4.0 of fragments. We got work with multiple Back Stack, new state manager, Fragment checks while the application is running, improved animations.

My name is Kirill Rozov… I do techie at Surf and am also an Android & Kotlin GDE. In the article I will tell you about the changes that have occurred in Fragment 1.4, and show you how to work with them.

FragmentContainerView.getFragment ()

One of the minor changes in this release is the ability to get Fragment from FragmentContainerView… Previously, to find a Fragment, you had to call FragmentManager.findFragmentById (int) or FragmentManager.findFragmentById (String). The problem with this approach is that you have to perform type conversion to the required one.

AndroidX Fragment 1.3 introduced a special ViewGroup for adding a Fragment to it. He got a new method FragmentConteinerView.getFragment () that allows you to get the Fragment added to it. There is no need to produce casts for the output type.

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

New state manager

In Android Fragment 1.4, the API was removed to enable the new state manager to be enabled. The new state manager appeared in the previous version of the library, and now it has become the main and only one.

The new state manager makes it easier to work with the state management Fragment, due to which there were many bugs. He also laid the foundations for new functionality. For example, for a multiple back stack, which will allow you to solve problems without crutches.

If you would like to learn more about Fragment refactoring, I recommend reading Ian Lake’s article “Fragments: rebuilding the internals“. Despite the changes under the hood, the expected behavior of the Fragment and API has not changed.

FragmentStrictMode

Fragment has been gaining momentum lately: it will clearly stay with us for a long time.

It is rather difficult to understand how to work correctly with the Fragment API, and keep track of all the changes. There was already a huge codebase, but there was no automatic tool for migrating to new APIs in AndroidX Fragment. It would be very logical to have some kind of API that can track this. And now he was introduced – welcome FragmentStrictMode

To get started, you need to set the validation policy in the FragmentManager:

supportFragmentManager.strictModePolicy =
     FragmentStrictMode.Policy.Builder()
         // Настраиваем реакцию на нарушения
         .penaltyDeath()
         .penaltyLog()
         // настраиваем какие нарушения отслеживать
         .detectFragmentReuse()
         .detectTargetFragmentUsage()
         .detectWrongFragmentContainer()
         .detectSetUserVisibleHint()
         // настраиваем исключения
         .allowVialotation(HomeFragment::class.java, WrongFragmentContainerViolation::class.java)
         // Создаём объект политик
         .build()

IMPORTANT! The policy object is set only for the current FragmentManager and will not be inherited by any child FragmentManager.

Response options for finding violations

penaltyDeath() – the reaction in which the application will crash with an error when a vulnerability is found. It is highly discouraged for use in production!

Reaction penaltyLog() similar to the previous one, but instead of a crash, there will be a message in Logcat.

The third type of response is the listener.

FragmentStrictMode.Policy.Builder()
     .penaltyListener() { vialotation: Violation ->  …  }

I recommend using a listener to track bugs in production builds and fix them later. It’s easy to do with Firebase Crashlytics, after all Violation Is a subclass of the class Throwable

FragmentStrictMode.Policy.Builder()
     .penaltyListener() { vialotation -> 
       Firebase.crashlytics.recordException(vialotation)
     }

Violations

What can you track? There are currently 6 bugs available.

detectFragmentReuse () – tracking the reuse of a Fragment that has been removed from the FragmentManager.

val firstFragment =
     fragmentManager.findFragmentByTag(FRAGMENT_TAG_FIRST) ?: return  
fragmentManager.commit {
     remove(firstFragment)
}

fragmentManager.commit {
     // Добавление Fragment, удаленного ранее
     add(R.id.fragment_container, firstFragment, FRAGMENT_TAG_FIRST)
}

detectFragmentTagUsage () – using tags when adding Fragment from XML.

<fragment
     android:name="dev.androidbroadcast.FirstFragment"
     android:tag="first"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     />

detectWrongFragmentContainer () fires when trying to add a Fragment not in FragmentContainerViewwhich is designed to work with it.

The rest of the existing violation checks are needed to prevent the deprecated API from being used:

Multi Back Stack

The main highlight of Snippets 1.4 is the support for multiple Back Stack.

What is the point: there is an app with AppBar or NavBar. According to the Material Design manual, when switching navigation tabs, we do not save history. But customers, designers and managers believe that it is necessary to save it – just like on iOS.

Previously, to implement this on Fragment in Android, you had to do crutches. With the arrival of Androidx Fragment 1.4, there is a new API for saving Fragment transactions and restoring them. Let’s figure out how this is done.

// Добавляем начальный Fragment
supportFragmentManager.commit {
     setReorderingAllowed(true)
     replace<HomeFragment>(R.id.fragment_container)
}

// Добавляем Fragment и помещаем в back stack
supportFragmentManager.commit {
     setReorderingAllowed(true)
     replace<ProfileFragment>(R.id.fragment_container)
     addToBackStack("my_profile")
}

// Добавляем ещё один Fragment и помещаем в back stack
supportFragmentManager.commit {
     setReorderingAllowed(true)
     replace<EditProfileFragment>(R.id.fragment_container)
     addToBackStack("edit_profile") // добавляем
}

Everything that was added to the back stack FragmentManager can now be saved.

supportFragmentManager.saveBackStack("profile")

As a result, only HomeFragment will be on the stack. All other transactions will be rolled back but saved with the label “profile”. You can restore these transactions later using a call, or delete.

// Восстановить back stack “profile” и применить все транзакции в нём
supportFragmentManager.restoreBackStack(“profile”)

// Удалить back stack “profile”
supportFragmentManager.clearBackStack(“profile”)

The Fragment Multiple back stacks API is already integrated with Jetpack Navigation 2.4.0… If you would like to know more about how it all works, read the Ian Lake article “Multiple back stacks“.

New Android Lint checks

  • UseGetLayoutInflater – using the wrong LayoutInflater in the DialogFragment.

  • DialogFragmentCallbacksDetector – overriding callback for Dialog, not DialogFragment.

  • FragmentAddMenuProvider – using the wrong Lifecycle when using the MenuProvider.

  • DetachAndAttachFragmentInSameFragmentTransaction – execution of attach and detach for the same Fragment within the same transaction.

I recommend running Android Lint code analysis after updating the Fragment in the project.


The new Fragment release turned out to be quite interesting. We got multiple Back Stacks and some really important features.

But I remember the promise Ian Lake made two years ago, in 2019, at the Android Dev Summit. He talked about plans to simplify the work with life cycle management (LC) Fragment and create only one life cycle. In theory, this will make it easier to interact with the Fragment. It is not clear what will happen to retain instance Fragment in this case: you have to wait and see.

What do you expect from the fragments, what would you like to see? Leave comments.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *