What is the difference between FragmentPagerAdapter with ViewPager with OffScreenLimit set to 1 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.
I think if I set the offscreenlimit to 1, it would destroy all fragments outside of the two next of the current fragment, and it behaves similar to a FragmentStatePagerAdapter. Is this correct?
The difference is exactly as it's written in docs. But it can be a little confusing.
FragmentPagerAdapter holds its fragments in the FragmentManager in detached state while they are not visible (while they are over the offscreen limit bounds) and FragmentStatePagerAdapter removes them from the FragmentManager.
The offscreenPageLimit is something little different. All fragments within it stays attached to the UI. Once they go over, they are either removed, or detached.
You can see it in sources of FragmentPagerAdapter (line 121) and FragmentStatePagerAdapter (line 144)
Related
I want to prevent fragment re-create in viewpager , in default way every time you navigate to a fragment in viewpager , android creates a new instance of that fragment.
setOffscreenPageLimit(x) can fix this problem but i don't want to load more fragments in activity's onCreate. Any idea to solve this problem and maintain fragment instance after select for next time?
There are two most used classes for View Pagers are:
FragmentPagerAdapter
FragmentStatePagerAdapter
and they look alike in many ways but not all.
What you need is FragmentPagerAdapter
This will keep the Fragment as you want and not being recreated each time as the following quote say from the official documentantion:
Implementation of PagerAdapter that represents each page as a Fragment that is persistently kept in the fragment manager as long as the user can return to the page.
And also here in the same documentation:
The fragment of each page the user visits will be kept in memory...
Although remember using this, memory will be your responsibility and you will have to manage memory of your Views check the number of pages you are having first if they are many, its not a nice idea to display 50 pages this way. Only may be less than 10 (Tabs may be its the best choice). You are good. Memory management is the only thing to take NOTE here as the documentation itself say:
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.
So change your adapter to FragmentPagerAdapter and your fragments will be kept in memory not recreated.
Try setting Fragment.setRetainInstance(true). If you use FragmentPagerAdapter, this will cause an existing fragment to 'live' and not get re-created. It will to get detached and re-attached instead.
Try this, where you set the view pager adapter
viewPager.setOffscreenPageLimit(numberOfFragments)
I've been searching for it and all I found was the difference between them. And that's not the point.
If you use FragmentStatePagerAdapter in a ViewPager, you'll end up doing the same as you'd do with FragmentPagerAdapter, but consuming much less memory. If that's true, why should I use the FragmentPagerAdapter?
What is the advantages of using FragmentPagerAdapter?
What is the advantages of using FragmentPagerAdapter?
Speed, particularly when you have an intermediate number of pages: enough to easily hold in memory but beyond the handful that ViewPager wants to hold onto itself. With FragmentStatePagerAdapter, as the user navigates the pager, the adapter destroys some fragments and creates new ones. That takes time, both in terms of the direct Java code and in terms of the impact upon garbage collection. If you do not need that in some circumstance, why pay the price?
FragmentStatePagerAdapter:
If your page contains more fragments better to use FragmentStatePagerAdapter because it will save only state
of the fragment.
FragmentPagerAdapter:
Where as FragmentPagerAdapter will keep each fragment in memory as a result it will consume more moemory.
For example if you have around 3 fragments[in Viewpager] which contains less images/bitmaps better to go with FragmentPagerAdapter
For optimisation better to define mViewPager.setOffscreenPageLimit(2);
Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state
if your structure depend on nested fragment and if you need to use childFragmentManager on inner fragment you might have a stack problem with FragmentStatePagerAdapter. when i got this problem i've changed FragmentStatePagerAdapter with FragmentPagerAdapter and it worked well.
Say I have a viewpager with multiple fragments that hold bitmaps. I use setOffScreenLimit(numberOfPagesInViewPager) to make sure that the fragments are instantly available at any time (this is a requirement of my app). Quite, obviously the more fragments I have, the more memory I will use because of the bitmaps inside the fragments and fragments being kept in memory.
Now, suppose that those fragments all show the same content and therefore hold the same bitmaps.
Would it be possible to create only one fragment and reuse it in the viewpager for all pages (and hence reducing the memory footprint to 1 fragment)?
In code I am thinking about something like this:
public class MyAdapter extends FragmentPagerAdapter {
private MyFragment mFragment;
public MyAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
mFragment = MyFragment.newInstance();
}
#Override
public Fragment getItem(int position) {
// Reuse mFragment for all pages in the viewpager
return mFragment;
}
}
This approach does not work however, as I am getting this type of error:
java.lang.IllegalStateException: Can't change tag of fragment MyFragment{4259a4d0 id=0x7f0a0074 android:switcher:2131361908:0}: was android:switcher:2131361908:0 now android:switcher:2131361908:1
Would it be possible to create only one fragment and reuse it in the viewpager for all pages (and hence reducing the memory footprint to 1 fragment)?
Not with FragmentPagerAdapter and FragmentStatePagerAdapter. And I doubt that it would work even with your own custom PagerAdapter.
If you use an app that has a ViewPager, you will notice that the ViewPager animates when swiping, so you see parts of two pages at one time. That will be difficult with only one page. This is why ViewPager requires at least three pages at all times, so it can handle swipes in either direction.
Beyond that, I cannot quite understand why users will want to flip through a series of identical pages in a ViewPager.
Is your fragment complex? If it just has one imageview, you can implement a viewpager that uses simple layout view or just an image view as a base container.
The fragment adapter is frankly more useful if each of your fragments are of different structural code.
Not 100% sure, but I believe fragments get destroyed and re-created by view pager. You could double-check this in debugger. If this is true, then the fragment could be a thin wrapper around a bitmap, and bitmap itself could be cached instead of a fragment. There are multiple strategies on caching bitmaps as described at http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html.
In my case I have 18 pages of a book. Some of the pages contain a lot of text data and the pager struggles in switching between these pages. Is there a workaround?
From the documantation:
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 maybe try to use the FragmentPagerAdapter instead.
I read the documentation for android pageadapter and fragmentpageadapter and I didn't see any difference. I mean one is a fragment and one isn't but.. is that all? I don't have really much experience with fragments so maybe thats why I don't notice any difference.
So whats the difference if I use a FragmentPagerAdapter or a PagerAdapter??
The difference is that you can use Fragments inside a FragmentPageAdapter. If you want to have fragments that are going to be used in other parts of your code this is your Adapter.
Otherwise if you only want to have code that isn't going to be reused, you can use PagerAdapter.
Implementation of PagerAdapter that uses a Fragment to manage each page. But I highly recommend to use FragmentStatePagerAdapter class also handles saving and restoring of fragment's state.
FragmentStatePagerAdapter 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.
When using FragmentPagerAdapter the host ViewPager must have a valid ID set.
Subclasses only need to implement getItem(int) and getCount() to have a working adapter.
Here is an example implementation of a FragmentStatePagerAdapter pager containing fragments of lists