androidandroid-fragmentsandroid-viewpagerandroid-pageradapter

How to get fragment reference from ViewPager


I am trying to get the reference to a specific Fragment called MyChatsFragment after instantiating it with a custom SectionPageAdapter.

First, I am adding the Fragments

    mSectionsPageAdapter.addFragment(new CatalogFragment());
    mSectionsPageAdapter.addFragment(new MyBooksfragment());
    mSectionsPageAdapter.addFragment(new MyChatsFragment());
    viewPager.setAdapter(mSectionsPageAdapter);

Then I am trying to retrieve MyChatsFragment this way:

 MyChatsFragment myChatsFragment = (MyChatsFragment) mSectionsPageAdapter
                                                                 .getRegisteredFragment(2);

Yet, getRegisteredFragment(2) returns null and while debugging I have noticed the following:

In the Adapter, instantiateItem is only being called twice, therefore adding CatalogFragment and MyBooksFragment to registeredFragments SparseArray. This would explain why getRegisteredFragment(2) returns null. But why MyChatsFragment is actually created and the app is perfectly functional if instantiateItem is not even called for it?

Why isn't MyChatsFragment being added to registeredFragments SparseArray while other fragments are?

Is getItem(position) a viable solution?

After checking this answer, I have adapted my SectionsPageAdapter by overriding instantiateItem and destroyItem as you will be able to check the below code:

public class SectionsPageAdapter extends FragmentPagerAdapter{
private final List<Fragment> mFragmentList = new ArrayList<>();
private final SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

public void addFragment(Fragment fragment)
{
    mFragmentList.add(fragment);
}


public SectionsPageAdapter(FragmentManager FM)
{
    super(FM);
}
@Override
public Fragment getItem(int position) {
   return mFragmentList.get(position);
}

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

@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);
    }
}

Note: If needed, I can share MyChatsFragment code.


Solution

  • Use viewPager.getAdapter.getItem(position); from your Activity or parent Fragment.

    Description (Modified) - As you wrote addFragment() adds a fragment to mFragmentList and you are adding fragment by this method too by calling:

    mSectionsPageAdapter.addFragment(new MyChatsFragment())
    

    And getItem() returns a fragment from mFragmentList where you added your fragment. So if you want to get MyChatsFragment reference just use:

    MyChatsFragment myChatsFragment = (MyChatsFragment) 
    mSectionsPageAdapter .getItem(position);
    

    or

    MyChatsFragment myChatsFragment = (MyChatsFragment) 
    viewPager.getAdapter.getItem(position);