Refresh images on FragmentStatePagerAdapter on resuming activity

wasyl picture wasyl · Dec 4, 2012 · Viewed 29.2k times · Source

I have created an activity that uses FragmentStatePagerAdapter to provide small gallery. However, I can't get it to refresh when activity resumes (after coming back from other activity, for example). Every time first two pictures will be blank, and only after i swipe two pictures to the side, they get refreshed. None of the answers I've found work (especially overriding getItemPosition())

I set it up like this:

mPagerAdapter = new PhotosPagerAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.photosViewPager);
mPager.setAdapter(mPagerAdapter);

Then I have FragmentStatePagerAdapter class:

private class PhotosPagerAdapter extends FragmentStatePagerAdapter{

    public PhotosPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return photos.size();   
    }

    @Override
    public Fragment getItem(int position) {
        ImageFragment f = new ImageFragment(position);
        return f;
    }

    @Override
    public int getItemPosition(Object object) {
        throw new RuntimeException();
        //return POSITION_NONE;
    }

}

As you probably noticed, I throw RuntimeException in getItemPosition, because I wanted to check when it's called. And it isn't called until I add something to list containing my pictures. Then ImageFragment class:

public class ImageFragment extends Fragment{

    int position;
    Bitmap mBitmap;
    int width;
    int height;
    ImageView img;

    public ImageFragment(){
    }

    public ImageFragment(int position){
        this.position = position;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        img = new ImageView(container.getContext());
        img.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        width = container.getWidth();
        height = container.getHeight();

        loadBitmap();

        return img;
    }       

    public void loadBitmap(){
        if (img == null){
            return;
        }
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(photos.get(position), options);
        options.inSampleSize = calculateInSampleSize(options, width/2, height/2);
        options.inJustDecodeBounds = false;
        mBitmap = BitmapFactory
                .decodeFile(photos.get(position), options);         

        img.setImageBitmap(mBitmap);
    }


    @Override
    public void onDestroyView() {
        mBitmap.recycle();
        super.onDestroyView();
    }       
}

Code is kinda messy after I tried to fix it... But: removing onDestroyView() doesn't work. I have put mPagerAdapter.notifyDataSetChanged() in several places that must be called (like onResume()), with no result. I'm getting kinda desperate with that.

Answer

logray picture logray · Dec 4, 2012

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)...