Refresh images on FragmentStatePagerAdapter on resuming activity
I was having a similar problem like your, after some research i created a nice script that avoid recreating fragments that are already there but at the same time allow you to update all visible/initiated fragment.
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.view.ViewGroup;
import java.util.WeakHashMap;
/**
* Created by TheCobra on 9/17/15.
*/
public abstract class FragmentAdvanceStatePagerAdapter extends FragmentStatePagerAdapter
{
private WeakHashMap<Integer, Fragment> mFragments;
public FragmentAdvanceStatePagerAdapter(FragmentManager fm)
{
super(fm);
mFragments = new WeakHashMap<Integer, Fragment>();
}
@Override
public Fragment getItem(int position)
{
Fragment item = getFragmentItem(position);
mFragments.put(Integer.valueOf(position), item);
return item;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object)
{
super.destroyItem(container, position, object);
Integer key = Integer.valueOf(position);
if (mFragments.containsKey(key))
{
mFragments.remove(key);
}
}
@Override
public void notifyDataSetChanged()
{
super.notifyDataSetChanged();
for (Integer position : mFragments.keySet())
{
//Make sure we only update fragments that should be seen
if (position != null && mFragments.get(position) != null && position.intValue() < getCount())
{
updateFragmentItem(position, mFragments.get(position));
}
}
}
@Override
public int getItemPosition(Object object)
{
//If the object is a fragment, check to see if we have it in the hashmap
if (object instanceof Fragment)
{
int position = findFragmentPositionHashMap((Fragment) object);
//If fragment found in the hashmap check if it should be shown
if (position >= 0)
{
//Return POSITION_NONE if it shouldn't be display
return (position >= getCount()? POSITION_NONE : position);
}
}
return super.getItemPosition(object);
}
/**
* Find the location of a fragment in the hashmap if it being view
* @param object the Fragment we want to check for
* @return the position if found else -1
*/
protected int findFragmentPositionHashMap(Fragment object)
{
for (Integer position : mFragments.keySet())
{
if (position != null &&
mFragments.get(position) != null &&
mFragments.get(position) == object)
{
return position;
}
}
return -1;
}
public abstract Fragment getFragmentItem(int position);
public abstract void updateFragmentItem(int position, Fragment fragment);
}
Copy that code into a file name "FragmentAdvanceStatePagerAdapter.java". Now in your adapter, extend from this one and override "getFragmentItem()" & "updateFragmentItem()". Whenever you call notifydatachange(), updateFragmentItem() will be called with all the fragment already created. When the adapter need to create a new fragment, getFragmentItem() will be called.
I hope that save and help a lot of people :)
Good Luck and happy Programming!!!
P.S. your adapter "getItem()" should be "getFragmentItem()" if you use this class.
Instead of returning POSITION_NONE
and creating all fragments again, you can do as I suggested here: Update ViewPager dynamically?
Dealing with fragment pager adapters can be a PITA.
Here are a few helpful tips:
ViewPager PagerAdapter not updating the View
Update ViewPager dynamically?
Generally speaking this one works 99% of the time...
Override getItemPosition in your PagerAdapter like this:
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
Sometimes even those don't work, I have to use the 'brute force' method and recreate the entire view again (from onCreate onwards)...
Never just use POSITION_NONE use
if(fragmentManager.getFragments().contains(object))
return POSITION_NONE;
else
return POSITION_UNCHANGED;
to avoid Fatal Exception: java.lang.IllegalStateException Fragment {} is not currently in the FragmentManager