Reputation: 524
I'm using a ViewPager
and displaying a lot of different Fragments
inside it, not only in content but they use different classes as well. The list to be displayed should be changed dynamically and even though I manage to swap items around and add new ones to the adapter(and calling notifyDataSetChanged
), if I try changing the next item it will still slide to it when using mPager.setCurrentItem(mPager.getCurrentItem() + 1);
I am just adding a new Fragment
between the current item and the current next one, it is displayed correctly in the adapter but as the next one was already preloaded then getItem
in the adapter is not even called.
Is there another method "stronger" than notifyDataSetChanged
that tells my ViewPager
that it should get the next item again?
CODE SAMPLES:
The add and get item methods inside my FragmentPagerAdapter
(only samples, not the actual code)
public void add(@NonNull Integer fragmentIndex) {
mFragmentOrder.add(fragmentIndex);
notifyDataSetChanged();
}
@Override
public Fragment getItem(int position) {
int selectedFragment = mFragmentOrder(position);
Fragment fragment;
switch (selectedFragment) {
case 1:
fragment = new FragmentA();
break;
case 2:
fragment = new FragmentB();
break;
case 3:
fragment = new FragmentC();
break;
default:
fragment = new FragmentD();
break;
}
return fragment;
}
This is the function used to go to the next item(I don't allow swiping)
public void goToNext() {
mPager.setCurrentItem(mPager.getCurrentItem() + 1);
}
EDITS:
Edit 1: I had already tried using a FragmentStatePagerAdapter
instead and setting the OffscreenPageLimit
to 0, but to no avail.
Edit 2: [Solution] Using a FragmentStatePagerAdapter
AND overwriting the getItemPosition
function to return POSITION_NONE
or the index in the appropriate cases solved the problem. For some reason even after implementing the right version of this function the normal FragmentPagerAdapter
kept delivering the wrong Fragment
.
Upvotes: 3
Views: 1382
Reputation: 3832
By default, FragmentPagerAdapter
assumes that the number and positions of its items remain fixed. Therefore, if you want to introduce for dynamism, you have to provide for it yourself by implementing the getItemPosition(Object object)
method in the inherited adapter class. A very basic (but unefficient) implementation would be this:
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
Every time the parent view is determining whether the position of one of its child views (items) has changed, this code will force the fragment to be recreated. If you want to avoid the recreation when unnecessary, you have to include some logic in the method. Something like this:
@Override
public int getItemPosition (Object object) {
if (fragmentOrder.indexOf(object) == -1) {
return POSITION_NONE;
} else {
return index;
}
}
Finally, pay attention to possible memory leaks by adding an onDestroyView
method to your fragments and nullifying the views you are using.
Here is a good discussion of these issues with the two PagerAdapter
s.
Upvotes: 1