I am having a problem managing a changing list of item using the FragmentStatePagerAdapter. Please check source here.
The problem is that when the underlying list changes, and I call notifyDataSetChanged
, the adapter does not rebuild it's internal list of fragments. Referring to the code in instantiateItem
:
@Override
public Object instantiateItem(ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
return f;
}
}
I believe the code in this comment is wrong! If I delete the item at position 0 in the list, and I call notifyDataSetChanged
, then the fragment at position 0 should be deleted. However the adapter has never updated the position of fragments in its own private list. Therefore it still shows the old, deleted, data.
I found this answer but it is a hack that relies on getItemPosition being called and then forcing the fragment to update it's views.
How is it possible to manage fragments in a changing list?
Per the ViewPager.dataSetChanged() source, it uses PagerAdapter.getItemPosition() to determine the new position of a item after a data change. By default, getItemPosition()
always returns POSITION_UNCHANGED, meaning it never destroys and recreates items it has already created.
Override getItemPosition()
to return the correct value if you want to update Fragments that already exist in response to a notifyDataSetChanged()
call. For example, always returning POSITION_NONE will always destroy every Fragment and recreate them from scratch (which, in most cases, is more work than needs to be done if items are just reordering).