androidandroid-fragmentsandroid-pageradapterfragmentstatepageradapter

PagerAdapter.getItem() crash with IllegalStateException: Fragment already added


I have this code for FragmentStatePagerAdapter.getItem():

(logd() is just a static method that calls Log.d()).

@Override
public Fragment getItem(int position) {

    logd("Fragment for position: " + position);

    Fragment currFragment = null;
    List<Fragment> allFragments = mFragmentManager.getFragments();
    if (allFragments.size() == 0) {

        logd("No Fragments cached.");
    } else {

        currFragment = allFragments.get(position);
        logd("Found a cached Fragment: " + currFragment);
    }

    if (currFragment == null) {

        currFragment = MyCustomFragment.create(position);
    }

    logd("Returning Fragment: Position: " + position + " Fragment: " + currFragment.toString());
    return currFragment;
}

But it keeps crashing with:

    --------- beginning of crash
2020-07-27 10:45:44.492 6271-6271/com.example.package E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.package, PID: 6271
    java.lang.IllegalStateException: Fragment already added: MyCustomFragment{7c7e778} (5f284a0f-a00f-4be2-8098-a3e8dc65c9cb) id=0x7f09024e}
        at androidx.fragment.app.FragmentStore.addFragment(FragmentStore.java:67)
        at androidx.fragment.app.FragmentManager.addFragment(FragmentManager.java:1563)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:405)
        at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2167)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1990)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1945)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1847)
        at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6592)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769)

This has me totally stumped. Can someone help why this crash is happening?

As far as I can make out, the same code construct works elsewhere in my app.

I did see several other SO questions with the same exception, but none that dealt specifically with Fragments inside ViewPager+TabLayout combinations.

Edit: Even this code crashes with the same exception:

@Override
public Fragment getItem(int position) {

    Fragment currFragment = MyCustomFragment.create(position);
    logd("Returning Fragment: Position: " + position + " Fragment: " + currFragment.toString());
    return currFragment;
}

Edit: Adding the code of MyCustomFragment.create():

public static MyCustomFragment create(int position) {

    Bundle args = new Bundle();
    args.putInt("position", position);
    MyCustomFragment f = new MyCustomFragment();
    f.setArguments(args);
    logd("Creating Fragment at position: " + position);
    return f;
}

Edit:

It seems that if I return new Fragment() from getItem(), everything works. If I return new MyCustomFragment() from getItem(), I get the crash. MyCustomFragment does not even have any constructor; it relies on the default one (though I did try with a no-arg constructor that just calls super(); still the crash persists).


Solution

  • The problem was that within MyCustomFragment, in the onCreateView() method, the IDE-stub code of return super.onCreateView() was left in place inadvertently. The superclass, Fragment, returns null from its onCreateView() under certain conditions. It appears that this null return from onCreateView() was creating the problem. I inflated a test layout in MyCustomFragment's onCreateView() and now the crash is gone.

    The exception looks incorrectly worded if that is indeed the case.