404

What is the difference between FragmentPagerAdapter and FragmentStatePagerAdapter?

About FragmentPagerAdapter Google's guide says:

This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs. The fragment of each page the user visits will be kept in memory, though its view hierarchy may be destroyed when not visible. This can result in using a significant amount of memory since fragment instances can hold on to an arbitrary amount of state. For larger sets of pages, consider FragmentStatePagerAdapter.

And about FragmentStatePagerAdapter:

This version of the pager is more useful when there are a large number of pages, working more like a list view. When pages are not visible to the user, their entire fragment may be destroyed, only keeping the saved state of that fragment. This allows the pager to hold on to much less memory associated with each visited page as compared to FragmentPagerAdapter at the cost of potentially more overhead when switching between pages.

So I have just 3 fragments. But all of them are separate modules with a large amount of data.

Fragment1 handles some data (which users enter) and passes it via activity into Fragment2, which is just a simple ListFragment. Fragment3 is also a ListFragment.

So my questions are: Which adapter should I use? FragmentPagerAdapter or FragmentStatePagerAdapter?

nbro
  • 15,395
  • 32
  • 113
  • 196
AlexMomotov
  • 7,418
  • 8
  • 24
  • 34
  • 2
    I think having only 3 Fragments qualifies you to use FragmentPagerAdapter. The tabs for these Fragments will probably all be visible simultaneously. – IgorGanapolsky May 28 '14 at 16:06
  • 1
    Answer to this question throws one more question http://stackoverflow.com/questions/9156406/whats-the-difference-between-detaching-a-fragment-and-removing-it – Piyush Kukadiya Mar 19 '17 at 13:24
  • 4
    there is `FragmentPagerAdapter` and `FragmentStatePagerAdapter` but what is `FragmentStateAdapter`? – the_prole Dec 17 '19 at 22:23

9 Answers9

318

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.

Emmanuel
  • 13,083
  • 4
  • 39
  • 53
  • I have multiple Buttons and TextViews in Fragment1 and ListView which generate items dynamically in Fragment2 and Fragment3. Do you think it is a good idea to use FragmentStatePagerAdapter and store all data in Activity, passing it to Fragments via Bundle? – AlexMomotov Sep 12 '13 at 08:36
  • 2
    @AlexMomotov Views in the Fragment's layout don't have anything to do with the choice of FragmentStatePagerAdapter. The question here is the amount of Fragments that will be paged through. – IgorGanapolsky May 28 '14 at 16:08
  • 1
    So basicaly there is nothing in favour of `FragmentPagerAdapter` to use it. – Tomasz Mularczyk Jul 02 '15 at 12:39
  • 3
    @Tomasz the advantage of `FragmentPagerAdapter` is that switching between fragments could be much faster, as the actual `Fragment` objects do not need to be rebuilt each time. On the other hand, this would end up using more memory holding the fragment objects in memory. – Richard Le Mesurier Nov 30 '16 at 08:36
  • I have 3 tabs/pages (that each show a WebView), so have used **FragmentPagerAdapter**. However, the last page still gets redrawn when I swipe across to it from the first page. To solve this, I have used `viewPager.setOffscreenPageLimit(2)`. – ban-geoengineering Jul 27 '18 at 16:56
  • @ban-geoengineering, yes, as *Phan Van Linh* has already written, when you start activity, you will have only two fragments created. Do you mean that Fragment1 and Fragment3 are redrawn on every swipe to them? – CoolMind Dec 27 '18 at 07:42
  • @CoolMind If I recall correctly, yes, the last/first of the three fragments were being **re**drawn every time I swiped to them from the first/last fragment, respectively. – ban-geoengineering Dec 28 '18 at 14:41
  • @Emmanuel What is purpose of overriding "containsItem" and "getItemId"? Are these overrides required if one is passing in new lists to the FragmentStatePagerAdapter implementation and calling notifyDataSetChanged? – the_prole Jul 14 '21 at 19:30
143

FragmentStatePagerAdapter:

  • with FragmentStatePagerAdapter,your unneeded fragment is destroyed.A transaction is committed to completely remove the fragment from your activity's FragmentManager.

  • The state in FragmentStatePagerAdapter comes from the fact that it will save out your fragment's Bundle from savedInstanceState 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 calls detach(Fragment) on the transaction instead of remove(Fragment).

  • This destroy's the fragment's view but leaves the fragment's instance alive in the FragmentManager.so the fragments created in the FragmentPagerAdapter are never destroyed.

Stephen
  • 9,899
  • 16
  • 90
  • 137
  • 2
    Why do you have 2 answers? – Jared Burrows Oct 16 '14 at 22:36
  • what is the benefit of keeping whole fragments in memory? – Tomasz Mularczyk Jul 02 '15 at 12:45
  • 4
    @Tomek : if the next fragment is already instantiated (i.e. FragmentPagerAdapter), it will be ready to render when you swipe to it, so the swipe animation will be smoother. With FragmentStatePagerAdapter, the next fragment instance may not exist until you swipe to it, and if it's a big fragment that is expensive to create, you may see a stutter in the animation. It's a question of performance vs. memory consumption. – Dalbergia Jul 21 '15 at 15:05
  • 2
    @Jared Burrows bcoz one is just _AnswerText_ which is good for small and static answers and the other is *AnswerStateText* which is for bigger and dynamic answers – Simple Fellow May 05 '18 at 06:19
70

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

Linh
  • 57,942
  • 23
  • 262
  • 279
  • Such a great way of conclusion! – Rahul Rastogi Oct 28 '19 at 14:21
  • nice explanation – gourav singhal Nov 27 '19 at 07:32
  • 1
    Nice explanation. You said that using FragmentStatePagerAdapter when having a lot of pages is good for performance. Did you mean that it is good for memory saving? The goal as I understand it is to preserve memory in case of possible many Fragment instances - so performance is the implicit benefit; the explicit goal is to preserve the memory – Richard Miller Apr 11 '20 at 13:53
39

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.

JDenais
  • 2,956
  • 2
  • 21
  • 30
  • So say I have 2 fragments, 1 recyclerview in fragment A , when I click on an item it changes the content of fragment B, say I do fragB.setText("blablabla"). I should use the state pagerthen ? – Ced Dec 03 '15 at 17:59
  • Not certain but I would say yes. Just try both, it is really easy and quick to change your code from one to another anyway. – JDenais Dec 03 '15 at 21:32
  • @JDenais Are you sure this is correct? I am using `FragmentPagerAdapter` in my activity that uses a ViewPager to show two fragments - where each fragment contains a list. My first list is called "All Reports" and the second list is "Favourite Reports". In the first list, if I tap the star icon for a report, it updates the database to toggle the favourite status of that report. I then swipe across and I successfully see this report in the UI of the second list. So maybe the instances are kept in memory but in some cases (e.g., mine) the content will actually update fine for FragmentPagerAdapter – ban-geoengineering Dec 01 '16 at 20:35
14

FragmentPagerAdapter stores the previous data which is fetched from the adapter while FragmentStatePagerAdapter takes the new value from the adapter everytime it is executed.

cyborg86pl
  • 2,597
  • 2
  • 26
  • 43
vinay kumar
  • 149
  • 1
  • 2
4

FragmentStatePagerAdapter = To accommodate a large number of fragments in ViewPager. As this adapter destroys the fragment when it is not visible to the user and only savedInstanceState of the fragment is kept for further use. This way a low amount of memory is used and a better performance is delivered in case of dynamic fragments.

Ashish Dwivedi
  • 8,048
  • 5
  • 58
  • 78
3

FragmentPagerAdapter: the fragment of each page the user visits will be stored in memory, although the view will be destroyed. So when the page is visible again, the view will be recreated but the fragment instance is not recreated. This can result in a significant amount of memory being used. FragmentPagerAdapter should be used when we need to store the whole fragment in memory. FragmentPagerAdapter calls detach(Fragment) on the transaction instead of remove(Fragment).

FragmentStatePagerAdapter: the fragment instance is destroyed when it is not visible to the User, except the saved state of the fragment. This results in using only a small amount of Memory and can be useful for handling larger data sets. Should be used when we have to use dynamic fragments, like fragments with widgets, as their data could be stored in the savedInstanceState.Also it won’t affect the performance even if there are large number of fragments.

Foroogh Varmazyar
  • 1,057
  • 1
  • 14
  • 18
1

Don't know about technical details but from my experience:
If you try to use FragmentStatePagerAdapter in a viewPager that in a fragment then your option menu of your sub-fragments could be messed up(or doesn't show up at all) if you navigate to another page and came back. But it will work with FragmentPagerAdapter.
As far as i can see onCreateOptionsMenu of sub-fragments not getting called until user clicked to a tab. This is probably intended but it was a nightmare for me.

Some pages i came accros during hopeless searches:
https://issuetracker.google.com/issues/37092407
OptionsMenu of Fragments in Viewpager showing each other's Buttons
Nested fragments in viewpager with different menus

PS: Any elegant solution or suggestion to this particular problem that uses FragmentStatePagerAdapter is welcomed

eddym
  • 648
  • 7
  • 11
0

according to doc :

There are two types of standard PagerAdapters that manage the lifecycle of each fragment: FragmentPagerAdapter and FragmentStatePagerAdapter. Both of them work well with fragments, but they are better suited for different scenarios:

  • The FragmentPagerAdapter stores the fragments in memory as long as the user can navigate between them. When a fragment is not visible, the PagerAdapter will detach it, but not destroy it, so the fragment instance remains alive in the FragmentManager. It will release it from memory only when the Activity shuts down. This can make the transition between pages fast and smooth, but it could cause memory issues in your app if you need many fragments.

  • The FragmentStatePagerAdapter makes sure to destroy all the fragments the user does not see and only keep their saved states in the FragmentManager, hence the name. When the user navigates back to a fragment, it will restore it using the saved state. This PagerAdapter requires much less memory, but the process of switching between pages can be slower.

Sanam Yavarpor
  • 348
  • 3
  • 10