This book is just what I was looking for. The three pieces I was having issues with were static vs. dynamic fragments, dialogue fragments and backstack management. This book covers all three of these in a manner that has really cleared up my understanding and improved my application design as a result.

Part 2: Building Apps with Android Studio

Part 3: Adopting the Android Mindset

Part 4: Understanding the Android Platform

Android Studio makes adding swipe navigation to your Android apps easy through the “Scrollable Tabs + Swipe” option of the Navigation Type selection in the New Project Wizard. Choosing this option works great as long as you have a static list of screens that the user “swipes” between.

When Static Screen Lists Aren’t Enough

The way swipe navigation works is that each screen is represented by an instance of a Fragment-derived class. These Fragment classes are then managed by a PagerAdapter-derived class which makes them, in effect, a scrollable list. Passing that PagerAdapter to a ViewPager presents that list in a way that the user can use a swipe-motion to move between screens.

The code generated by Android Studio provides a custom PagerAdapter class that derives from FragmentPagerAdapter. Basically all one has to do is override the getItem method and return the desired Fragment for each screen position (you’ll also need to override getCount and getPageTitle but those are super simple). What happens though is that the FragmentPagerAdapter class is designed such that once a Fragment instance is returned for a given position that Fragment is permanently in that position. Once this happens, you can, of course, make changes to the contents of the Fragment but there’s no way to provide a different Fragment instance for that position which is often what’s necessary.

The comments in the generated class indicate that using FragmentStatePagerAdapter instead of FragmentPagerAdapter as the base class allows for more dynamic management of the Fragment instances. Reading the FragmentStatePagerAdapter documentation indicates that we can notify our FragmetStatePagerAdapter instance of a change in the list of screens (in other words that we’d like to use new Fragment instances) by calling the notifyDataSetChanged method. But that’s only part of the story.

Once you call this method what you’ll normally see is that screens that were previously visited still have the old Fragment instances but screens being visited for the first time have the new Fragment instances. If you have a large number of screens and scroll back and forth between them you may see some of the older screens eventually show a new Fragment instance.

Not really the consistent user experience we’re looking for 🙂

So what’s the problem?

What’s happening is that FragmentStatePagerAdapter is trying to be efficient and only create new Fragment instances when necessary. To determine when to request new Fragment instances after a call to the notifyDataSetChanged method, FragmentStatePagerAdapter calls its getItemPosition method to see if an existing Fragment can be used in its current or possibly a different position without having to recreate it. What we have to do is tell the FragmentStatePagerAdapter instance that we don’t want to use the existing Fragment instance.

To do that we need to override getItemPosition as follows

public int getItemPosition(Object object) {
// Causes adapter to reload all Fragments when
// notifyDataSetChanged is called
return POSITION_NONE;
}

By returning POSITION_NONE we’re telling the FragmentStatePagerAdapter instance to discard that Fragment and just create new ones for every screen position.

You’ve probably noticed that Android Studio doesn’t have a “clean” menu option. But we know that, like any build environment, there are intermediate files created that we may want to occasionally remove.

It turns out the solution is the command line. Simply open a command line in your project’s root folder (Usually named something like MyAppProject) and run the following command

gradlew clean

You’ll see something like this…

Notice that you get a bit of an unexpected message, “BUILD SUCCESSFUL”. This simply indicates that it has gone through and successfully cleaned out the intermediate files. I’ve found that when dealing with larger projects its not uncommon to reduce the amount of disk space used by the project by 70% or more.

So a bit of an unexpected solution (especially for those who’ve been in a Windows environment for a long time) but an easy one.

I need to take a minute to thank my beautiful wife, Bonnie. As you might imagine, I’ve been putting in a lot of hours these past few months and would never have been able to get through it all without her. Her patience and support never end. Bonnie I love you!!