I’m having a really hard time to recover from configuration changes with ViewPager.
What I want is save the current pager position so that after a config change the same page will be visible. To do that, I save pager.getCurrentItem() and restore it using pager.setCurrentItem. Just that this doesn’t work: setCurrentItem actually attempts to recreate that page instead of selecting it! And that’s even though the page has already been created.
Now I’m not sure if I missed something when implementing the adapter that’s backing it, but is there a pitfall to setCurrentItem and when ViewPager thinks that it’s fully constructed? Looking at the code of that function though, it makes no sense to me; it seems to always try to recreate a page, except when there are no items at all:
void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {
// these are the only checked that make this method return
if (mAdapter == null || mAdapter.getCount() <= 0) {
setScrollingCacheEnabled(false);
return;
}
if (!always && mCurItem == item && mItems.size() != 0) {
setScrollingCacheEnabled(false);
return;
}
// ... removed some init code
mCurItem = item;
populate();
// ...
}
As you can see, populate() is always called, except when there are either no items at all, or the item you’re trying to select was already selected. What gives? That doesn’t make sense to me.
Not exactly, at least in terms of how I read the code.
populate()will calladdNewItem(), which callsinstantiateItem()on thePagerAdapter. TheFragmentPagerAdapterimplementation ofPagerAdapterwill use an existing fragment if available, otherwise it calls out togetItem()so you create the page yourself. So, if you usesetRetainInstance(true)with your page fragments, and you are usingFragmentPagerAdapter, they should be reused.FragmentStatePagerAdapterseems more complicated, and if you are rolling your ownPagerAdaptersans fragments, it is up to you to implement a caching mechanism.