FragmentPagerAdapter getItem is not called
Asked Answered
M

7

129

I am not able to reuse fragment in FragmentPagerAdapter.. Using destroyItem() method, It is deleting the fragment but still does not called getItem() again..There are just 2-3 Images so I am using FragmentPagerAdapter Instead of FragmentStatePagerAdapter..

public class ExamplePagerAdapter extends FragmentPagerAdapter {

    ArrayList < String > urls;
    int size = 0;
    public ExamplePagerAdapter(FragmentManager fm, ArrayList < String > res) {
        super(fm);
        urls = res;
        size = urls.size();
    }

    @Override
    public int getCount() {
        if (urls == null) {
            return 0;
        } else {
            return size;
        }

    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        FragmentManager manager = ((Fragment) object).getFragmentManager();
        FragmentTransaction trans = manager.beginTransaction();
        trans.remove((Fragment) object);
        trans.commit();
    }

    @Override
    public Fragment getItem(int position) {

        Fragment fragment = new FloorPlanFragment();
        Bundle b = new Bundle();
        b.putInt("p", position);
        b.putString("image", urls.get(position));
        Log.i("image", "" + urls.get(position));
        fragment.setArguments(b);
        return fragment;
    }
}

And In FragmentActivity,

pager.setAdapter(new ExamplePagerAdapter(getSupportFragmentManager(), res2)); 
Megavolt answered 25/9, 2012 at 11:21 Comment(2)
Is there a particular reason you overrode destroyItem()? That is not necessary.Cowgirl
to initialize again use FragmentStatePagerAdapter also call when you override it super.destroyItem(container, position, object);Birkle
M
317

KISS Answer:

Simple use FragmentStatePagerAdapter instead of FragmentPagerAdapter.

I got the answer.. Firstly I thought to delete this question as I am doing a very silly mistake but this answer will help someone who is facing the same problem that Instead of FragmentPagerAdapter, use FragmentStatePagerAdapter.

As @BlackHatSamurai mentioned in the comment:

The reason this works is because FragmentStatePagerAdapter destroys as Fragments that aren't being used. FragmentPagerAdapter does not.

Megavolt answered 25/9, 2012 at 12:0 Comment(11)
Hate to be another 'me too!' post, but yeah >.< Thanks for not deleting the question.Palembang
My guess would be something along the lines of the fragments getting dumped into a recycling bin for later use when destroyed, so that when a new pager gets created, it gets filled with recycled fragments. Could probably also be fixed by not putting any content specific code in the getItem call (such as setting an image based on the pagers variables, arrays ect...)Discover
The reason this works is because FragmentStatePagerAdapter destroys as Fragments that aren't being used. FragmentPagerAdapter does not.Lawrenson
@Blaine thanks, you cleared my mind. Btw, thank you bro, you saved me from a big problem.Taynatayra
Just for future reference for those who may find this while searching for a specific problem they're having; read up on both FragmentPagerAdapter and FragmentStatePagerAdapter. They behave differently for a reason and your specific use might require one over the other.Forgather
@najibputhawala I used FragmentStatePagerAdapter but still facing same issue. getItem() not calledJeffrey
Thank you for your answer. Actually Everyone did a silly mistake :DLovejoy
Thanks for sharing your answer, you saved me a lot of time. +1Furor
@Megavolt what is a kiss answer?Dressel
Thanks for sharing this answer spent almost 2hrs debugging, trying different things.Albany
I have this problme even with you solution.Stclair
M
173

Using a FragmentStatePagerAdapter didn't fully fix my problem which was a similar issue where onCreateView was not being called for child fragments in the view pager. I am actually nesting my FragmentPagerAdapter inside of another Fragment therefore the FragmentManager was shared throughout all of them and thus retaining instances of the old fragments. The fix was to instead feed an instance of the getChildFragmentManager to the constructor of the FragmentPagerAdapter in my host fragment. Something like...

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

The getChildFragmentManager() method is accessible via a fragment and this worked for me because it returns a private FragmentManager for that fragment specifically for situations in which nesting fragments is needed.

  • Keep in mind however to use getChildFragmentManager() your minimum API version must be atleast 17 (4.2), so this may throw a wrench in your gears. Of course, if you are using fragments from the support library v4 you should be okay.
Munsey answered 16/4, 2015 at 5:33 Comment(3)
This is the correct answer. The problem is due that the fragments nested in other fragments should use getChildrenFragmentManager() instead of getFragmentManager().Myosotis
I same case of nested fragment i still have problem. In my case my last items ( for example 9,10) getItem not called! it is very odd.Stclair
does not work for me because this: adapter = new MyAdapter( ChildFragmentManager ); will cause: Error CS1503 Argument 1: cannot convert from 'Android.App.FragmentManager' to 'Android.Support.V4.App.FragmentManager'Chandlery
O
9

Override long getItemId (int position)

FragmentPagerAdapter caches the fragments it creates using getItem. I was facing the same issue- even after calling notifyDataSetChanged() getItem was not being called.

This is actually a feature and not a bug. You need to override getItemId so that you can correctly reuse your fragments. Since you are removing fragments, your positions are changing. As mentioned in the docs:

long getItemId (int position)

Return a unique identifier for the item at the given position.

The default implementation returns the given position. Subclasses should override this method if the positions of items can change.

Just provide a unique id to each fragment and you're done.

Using a FragementStatePagerAdapter or returning POSITION_NONE in int getItemPosition (Object object) is wrong. You will not get any caching.

Oleic answered 16/2, 2018 at 15:17 Comment(4)
This one was the correct answer. I had to provide different ids for the fragments in getItemId AND adjust getItemPosition to return POSITION_NONE IF the fragment should be removed. I have a enum flag for that. After that getItem will be called.Cubby
Thank you @MuratKaragöz for the +50 :)Oleic
Thanks a lot, it works better with this method overrided.Gustavo
Thank you, it works for me too. It's only working solution for me after trying everything.Godfree
V
5

I did what @kanika and @Jraco11 had posted but I still had the problem.

So, after a lot of changes, I found one that worked for me and was added to my FragmentPagerAdapter the next code:

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

According to what I read, getItemPosition is used to notify the ViewPager whether or not to refresh an item, and to avoid updates if the items at the visible positions haven't changed.

Vaughnvaught answered 28/4, 2016 at 2:39 Comment(0)
J
4

method getItem() is used only to create new items. Once they created, this method will not be called. If you need to get item that is currently in use by adapter, use this method:

pagerAdapter.instantiateItem(viewPager, TAB_POS)
Jessikajessup answered 30/10, 2018 at 10:23 Comment(0)
A
2

There are two different scenarios : 1.) You have same layout for every pager : In that case, it will be better if you'll extend your custom adapter by PagerAdapter and return a single layout.

2.) You have different layout for every pager : In that case, it will be better if you'll extend your custom adapter by FragmentStatePagerAdapter and return different fragmets for every pager.

Abroad answered 21/1, 2015 at 9:37 Comment(0)
H
0

I found that setting a listener on the tab-layout stopped this from being called, probably because they only have space for one listener on tabLayout.setOnTabSelectedListener instead of an array of listeners.

Hindsight answered 4/2, 2016 at 7:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.