Engineering

The life of a Fragment in a ViewPager - pro tip for Android developers

I suppose that every platform has a few black sheep - not fully thought-out elements and their workarounds, necessarily taken as solutions that most programmers have probably heard of, taken in the dark as the best of the worst because it works, somehow… and so far there has been no one with the ambition to end our misery and propose a decent solution.

Not this time.

Do you remember the time when Fragments were introduced to Android system? When they appeared, programmers didn't approach them very confidently. Activities were easier to understand, worked well for a long time and you could rely on them. Those who wanted to have something fancier, created custom Views. Using Fragments required controlling their own stack, there were problems with nesting them and dilemmas as to whether it was better to create a Fragment or just Activity is enough.

Mosaic

Gaudi was able to create something beautiful out of the fragments.
Image from https://pxhere.com/pl/photo/1157000

However, the very idea of the Fragments was good enough to overcome all fears and weaknesses, and over time the problems with the Fragments were fixed. Well, not entirely! One small village of indomitable...

Asterix and Obelix

© 2019 LES ÉDITIONS ALBERT RENÉ / GOSCINNY-UDERZO

I mean, ViewPagers. Yes, the ones with Fragments. Have you ever wanted to know the state of a particular Fragment? To know if it is currently active in the ViewPager? Have you wondered why its neighbours had also called onResumed, even though they are not visible at all? Have you been worried that your solution using getUserVisibleHint or onPageChangedListener doesn't look very nice and may be a source of other problems?

Worry no more!

Thanks to the great green god of all the sweets and open source… well, actually, thanks to the AndroidX team. They are like those little good elves, working hard behind the scenes to make Android development easier and more enjoyable.

Imagine that you can set the maximum possible lifecycle state of the Fragment in the FragmentTransaction. Yes, it's true. Using this one line of code:

setMaxLifecycle(@NonNull Fragment fragment, @NonNull Lifecycle.State state)

You can control what states are possible for a given Fragment. But this isn't the end of good Android news. What's more, the AndroidX team did the work for us and introduced this solution into FragmentPagerAdapter and FragmentStatePagerAdapter. From now on, with one additional parameter in the constructor, it is possible to use this new solution:

FragmentPagerAdapter(@NonNull FragmentManager fm, @Behavior int behavior)

Where behavior is one of the following:

@Deprecated public static final int USE_SET_USER_VISIBLE_HINT = 0;

public static final int RESUME_ONLY_CURRENT_FRAGMENT = 1;

As you can see the first one is Deprecated so it is recommended to use the new way.

Thanks to this, the one Fragment that is currently displayed in the ViewPager will have a lifecycle state RESUMED. The rest will not have a higher than STARTED. Simple yet effective, right?

Applause

Image from http://gph.is/2jjT1px

This solution was first presented in androidx.fragment 1.1.0-alpha07 and is still in a state of development. In the 1.1.0-alpha08 version, a bug was fixed, which was causing every instantiated item (including the invisible one) have the RESUMED state by default and only after a few milliseconds changed to the correct one. It is possible that the introduction of a stable version of the new ViewPager2 based on RecyclerView will solve the problems with the ViewPager once and for all (hopefully), but anyway, we can be thankful for this Android update and glad that the long-standing difficulties are being solved.

For further information, please refer to androidx.fragment release notes.