IllegalStateException: <MyFragment> is not currently in the FragmentManager

Viewed 22698

I know it sounds like a duplicate of FragmentStatePagerAdapter IllegalStateException: <MyFragment> is not currently in the FragmentManager but his solution isn't relevant to my case.

I'm getting the following crash very rarely:

java.lang.RuntimeException: Unable to pause activity {MyActivity}:

...

Caused by: java.lang.IllegalStateException: Fragment MyFragment {40648258 id=0x7f070051} is not currently in the FragmentManager at android.support.v4.app.FragmentManagerImpl.putFragment(MT:516) at android.support.v4.app.FragmentStatePagerAdapter.saveState(MT:185) at android.support.v4.view.ViewPager.onSaveInstanceState(MT:881)

...

at android.view.View.saveHierarchyState(View.java:6238) at com.android.internal.policy.impl.PhoneWindow.saveHierarchyState(PhoneWindow.java:1522) at android.app.Activity.onSaveInstanceState(Activity.java:1138) at android.support.v4.app.FragmentActivity.onSaveInstanceState(MT:480) at MyActivity.onSaveInstanceState(MT:336)

It seems like this is the weird code I can't understand from FragmentStatePagerAdapter:

for (int i=0; i<mFragments.size(); i++) {
    Fragment f = mFragments.get(i);
    if (f != null) {
        if (state == null) {
            state = new Bundle();
        }
        String key = "f" + i;
        mFragmentManager.putFragment(state, key, f);
    }
}

It looks like the adapter gets my Fragment from mFragments but can't add its state to FragmentManager.

I've couldn't find any way to recreate this on my test devices, only received this from some users.

I'm using support package v4.

Any help? Thanks.

12 Answers

Are you calling FragmentStatePagerAdapter.instantiateItem() from your own code? Generally, the ViewPager should be the only client that calls this method, however, it's easy to come across workarounds for other limitations that rely on this method.

Due to the way FragmentStatePagerAdapter works, I would guess that the adapter has instantiated the Fragment, added it to it's internal collection of Fragments, and even began a transaction to add that Fragment to the FragmentManager, but that fragment transaction has not been committed or executed. This is exactly what instantiateItem() does when it hasn't already instantiated the requested Fragment.

Another method, FragmentStatePagerAdapter.finishUpdate() is responsible for committing the transaction as well as for executing the pending transactions. finishUpdate() must be called after instantiateItem() or else the Fragment may not be added to the FragmentManager.

Try something like this:

// Get the current Fragment presented by the ViewPager.
pagerAdapter.startUpdate(viewPager);
Fragment fragment = pagerAdapter.instantiateItem(viewPager, viewPager.getCurrentItem());
pagerAdapter.finishUpdate(viewPager);
return fragment;

startUpdate() has an empty implementation as of API level 19.

Try using

use fragmentTransaction.add()
Related