bhbbby
bhbbby

Reputation: 45

How to replace fragment in viewpager after instantiation?

I understand that the offscreen page limit for a viewpager must be at least 1. I am trying to dynamically change the fragments in my viewpagers as I am constantly grabbing information from a server. For example, I have Fragments A, B, C instantiated when I am viewing Fragment B. I want to change Fragment A's info, so I update it and call notifyDataSetChanged(). I have not created a new Fragment and inserted it in its place, but changed the imageview associated with the original fragment.

However, once I try to navigate to A, I run into an error saying "Fragment is not currently in the FragmentManager "

Can anyone explain to me how I'd be able to jump back and forth between immediate pages in a viewpager while allowing these pages to change their views?

Upvotes: 0

Views: 173

Answers (2)

JDJ
JDJ

Reputation: 4328

To do that, you should create a FragmentPagerAdapter that saves references to your pages as they are created. Something like this:

public class MyPagerAdapter extends FragmentPagerAdapter {
    SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

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

    @Override
    public Fragment getItem(int position) {
        switch (position)
        {
        case 0:
            return MyListFragment.newInstance(TAB_NAME_A);  
        case 1:
            return MyListFragment.newInstance(TAB_NAME_B);
        case 2:
            return MyListFragment.newInstance(TAB_NAME_C);
        default:
            return null;
        }           
    }

    @Override
    public int getCount() {
        // Show 3 total pages.
        return TOTAL_PAGES;
    }       

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);

        registeredFragments.put(position, fragment);

        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);

        super.destroyItem(container, position, object);
    }

    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }   
} 

You can access a particular page like this:

((MyListFragment) myPagerAdapter.getRegisteredFragment(0)).updateUI();

Where updateUI() is a custom method that updates your list on that page and calls notifyDataSetChanged().

Upvotes: 0

Andrii Bas
Andrii Bas

Reputation: 623

I didn't do that, but my suggestion will be not to try to. Android does a lot of magic under the hood, and it is very possible you'll face a lot of issues trying to implement what you want. I had an experience with ListView when I was trying to save contentView for each list item, so that Android will render them only once, after the whole day I gave up the idea because every time I've changed the default behavior, something new came up (like exceptions that views are having two parents). I've managed to implement that, but the code was really awful.

Why don't you try, for example, save the image you've downloaded on the disc, and retrieve if when fragment actually appears on the screen ? Picasso library could help in this case

Upvotes: 1

Related Questions