What is the difference between FragmentPagerAdapter and FragmentStatePagerAdapter?
Like the docs say, think about it this way. If you were to do an application like a book reader, you will not want to load all the fragments into memory at once. You would like to load and destroy Fragments
as the user reads. In this case you will use FragmentStatePagerAdapter
. If you are just displaying 3 "tabs" that do not contain a lot of heavy data (like Bitmaps
), then FragmentPagerAdapter
might suit you well. Also, keep in mind that ViewPager
by default will load 3 fragments into memory. The first Adapter
you mention might destroy View
hierarchy and re load it when needed, the second Adapter
only saves the state of the Fragment
and completely destroys it, if the user then comes back to that page, the state is retrieved.
FragmentStatePagerAdapter:
-
with
FragmentStatePagerAdapter
,your unneeded fragment is destroyed.A transaction is committed to completely remove the fragment from your activity'sFragmentManager
. -
The state in
FragmentStatePagerAdapter
comes from the fact that it will save out your fragment'sBundle
fromsavedInstanceState
when it is destroyed.When the user navigates back,the new fragment will be restored using the fragment's state.
FragmentPagerAdapter:
-
By comparision
FragmentPagerAdapter
does nothing of the kind.When the fragment is no longer needed.FragmentPagerAdapter
callsdetach(Fragment)
on the transaction instead ofremove(Fragment)
. -
This destroy's the fragment's view but leaves the fragment's instance alive in the
FragmentManager
.so the fragments created in theFragmentPagerAdapter
are never destroyed.
Here is a log lifecycle of each fragment in ViewPager
which have 4 fragment and offscreenPageLimit = 1 (default value)
FragmentStatePagerAdapter
Go to Fragment1 (launch activity)
Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart
Go to Fragment2
Fragment3: onCreateView
Fragment3: onStart
Go to Fragment3
Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach
Fragment4: onCreateView
Fragment4: onStart
Go to Fragment4
Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy
FragmentPagerAdapter
Go to Fragment1 (launch activity)
Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart
Go to Fragment2
Fragment3: onCreateView
Fragment3: onStart
Go to Fragment3
Fragment1: onStop
Fragment1: onDestroyView
Fragment4: onCreateView
Fragment4: onStart
Go to Fragment4
Fragment2: onStop
Fragment2: onDestroyView
Conclusion: FragmentStatePagerAdapter
call onDestroy
when the Fragment is overcome offscreenPageLimit
while FragmentPagerAdapter
not.
Note: I think we should use FragmentStatePagerAdapter
for a ViewPager
which have a lot of page because it will good for performance.
Example of offscreenPageLimit
:
If we go to Fragment3, it will detroy Fragment1 (or Fragment5 if have) because offscreenPageLimit = 1
. If we set offscreenPageLimit > 1
it will not destroy.
If in this example, we set offscreenPageLimit=4
, there is no different between using FragmentStatePagerAdapter
or FragmentPagerAdapter
because Fragment never call onDestroyView
and onDestroy
when we change tab
Github demo here
Something that is not explicitly said in the documentation or in the answers on this page (even though implied by @Naruto), is that FragmentPagerAdapter
will not update the Fragments if the data in the Fragment changes because it keeps the Fragment in memory.
So even if you have a limited number of Fragments to display, if you want to be able to refresh your fragments (say for example you re-run the query to update the listView in the Fragment), you need to use FragmentStatePagerAdapter.
My whole point here is that the number of Fragments and whether or not they are similar is not always the key aspect to consider. Whether or not your fragments are dynamic is also key.
FragmentPagerAdapter
stores the previous data which is fetched from the adapter while FragmentStatePagerAdapter
takes the new value from the adapter everytime it is executed.