FragmentManager is already executing transactions after using method setOffscreenPageLimit()

Mero_vic280 picture Mero_vic280 · Oct 17, 2016 · Viewed 22.1k times · Source

i have a navigation drawer with a number of fragments and one of them is a tablayout with two recyclerview fragments , the RecyclerView items disappear after switching between navigation drawer fragments , i found a solution that i need to use method setOffscreenPageLimit() with the ViewPager but it gives me the bug that is mentioned in the question title

here is my logcat

java.lang.IllegalStateException: FragmentManager is already executing transactions
                                                                               at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1626)
                                                                               at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:679)
                                                                               at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143)
                                                                               at android.support.v4.view.ViewPager.populate(ViewPager.java:1240)
                                                                               at android.support.v4.view.ViewPager.populate(ViewPager.java:1088)
                                                                               at android.support.v4.view.ViewPager.setOffscreenPageLimit(ViewPager.java:852)
                                                                               at com.amir.ahmed.EELUStudentUnion.SelectionFragment.setupViewPager(SelectionFragment.java:59)
                                                                               at com.amir.ahmed.EELUStudentUnion.SelectionFragment.onActivityCreated(SelectionFragment.java:40)
                                                                               at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:2089)
                                                                               at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1133)
                                                                               at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1290)
                                                                               at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)
                                                                               at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1677)
                                                                               at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:536)
                                                                               at android.os.Handler.handleCallback(Handler.java:739)
                                                                               at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                               at android.os.Looper.loop(Looper.java:158)
                                                                               at android.app.ActivityThread.main(ActivityThread.java:7225)
                                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

an that is the tab layout fragment code

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    viewPager = (ViewPager) getActivity().findViewById(R.id.viewpager);
    setupViewPager(viewPager);

    viewPager.setOffscreenPageLimit(2);

    tabLayout = (TabLayout) getActivity().findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(viewPager);
    setupTabIcons();
}



private void setupViewPager(ViewPager viewPager) {
    ViewPagerAdapter adapter = new ViewPagerAdapter(getFragmentManager());
    adapter.addFrag(new Courses(), "IT");
    adapter.addFrag(new CoursesBussiness(), "Business");
    viewPager.setAdapter(adapter);
}

Answer

Weidian Huang picture Weidian Huang · Dec 31, 2016

I encountered the similar issue as you, after several hours research, I found the issue. If your ViewPager is created inside the Fragment, you need to use getChildFragmentManager() for the FragmentPagerAdapter, rather than getFragmentManager().

So your setupViewPager() method should look like this.

private void setupViewPager(ViewPager viewPager) {
    ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
    adapter.addFrag(new Courses(), "IT");
    adapter.addFrag(new CoursesBussiness(), "Business");
    viewPager.setAdapter(adapter);
}

The root cause of the issue is you embeded Fragments inside the Fragment, that's why it will throw the exception.

java.lang.IllegalStateException: FragmentManager is already executing transactions

According to the Google's docs:

You can now embed fragments inside fragments. This is useful for a variety of situations in which you want to place dynamic and re-usable UI components into a UI component that is itself dynamic and re-usable. For example, if you use ViewPager to create fragments that swipe left and right and consume a majority of the screen space, you can now insert fragments into each fragment page. To nest a fragment, simply call getChildFragmentManager() on the Fragment in which you want to add a fragment. This returns a FragmentManager that you can use like you normally do from the top-level activity to create fragment transactions.