Android: Viewpager and FragmentStatePageAdapter

Android Noob picture Android Noob · Aug 2, 2011 · Viewed 11.7k times · Source

I'm designing an app that allows users to flip between multiple pages in a ViewPager. I've been struggling trying to figure out how it is possible to remove a Fragment instance from a page when it is no longer visible on screen, cache it (to, say, a HashMap), and then restore it so that when the user flips back to that page, the views and everything else in it will be in the same state it was before removal. For example, my first page is a login screen that makes certain layout elements on that particular page visible/invisible on a successful login. When I flip forward enough pages then flip back to the first page, the layout is reset. This becomes more of a problem for another one of my pages which contains a huge, horizontal/vertical scrolling grid of data that I use a thread in the background to draw when it initializes. I use a progress dialog to notify the user of loading progress and that becomes really annoying everytime I have to load it.

So I did some research...

I browsed through the source code for FragmentStatePageAdapter and in the destroyItem() callback, the state of the Fragment instance being removed is saved to an ArrayList. When a new instance of the Fragment is being created in the instantiateItem() callback, if an instance of an item doesn't already exist (they keep track of this by using an ArrayList), a new Fragment instance is created and its saved state is initialized with the corresponding Fragment.SavedState data. Unfortunately, this data does not include the state that the Views were in although I noticed that for pages with a GridView/ListView, the state of the Views were somehow restored (if I scrolled to some random position, flipped a few pages and came back, it would not be reset).

According to the API:

The saved state can not contain dependencies on other fragments -- that is it can't use putFragment(Bundle, String, Fragment) to store a fragment reference because that reference may not be valid when this saved state is later used. Likewise the Fragment's target and result code are not included in this state.

Being a noob to Android, I'm not quite sure I understand the last statement.

That being said, is there any way to cache View state? If not, I think I'll just go ahead and go with leaving all the fragment pages in memory.

Answer

rui.araujo picture rui.araujo · Aug 11, 2011

I had the same problem problem and solved it by implementing these two functions

    public void onSaveInstanceState (Bundle outState)
    public void onActivityCreated (Bundle savedInstanceState)

on the fragments that I wanted to save. On the first function, you should save in the Bundle the date that you need to restore the views ( in my case I had a bunch of spinner so I used an int array to save their positions). The second function, which is called when restoring your fragment, is where you implement the restoring process.

I hope this helps. I also made my adapter to inherit from FragmentStatePageAdapter but I am not sure that this is mandatory.