FragmentManager is already executing transactions after using method setOffscreenPageLimit()
Asked Answered
S

3

17

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);
}
Satisfy answered 17/10, 2016 at 19:17 Comment(0)
V
52

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.

Valgus answered 31/12, 2016 at 6:41 Comment(3)
I have been having this issue right from September 2016 and your answer helped me to solve it. Thanks a ton!!!!Flail
this answer is absolutely correct!, please accept it. tnx @weidianBoschvark
Not worked for me. When I add TabLayout select in the onAttachFragment method that error occurred.Marivaux
C
2

I think the real answer would be to call setOffscreenPageLimit before setting the adapter, because after the adapter is set, the ViewPager will start populate the child fragments. That's why it will create a race condition between the child fragments instantiation and setting page limits. If the page limit is smaller than default I think it will have to destroy some fragments while trying to create them.

Solution

viewPager.setOffscreenPageLimit(2);
...
viewPager.setAdapter(adapter);

Reason

Checking the source code of ViewPager the default offscreen pages is 1 (DEFAULT_OFFSCREEN_PAGES). Any other value used for setOffscreenPageLimit() will trigger a populate() call inside the ViewPager.

public void setOffscreenPageLimit(int limit) {
    if (limit < DEFAULT_OFFSCREEN_PAGES) {
        Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "
                + DEFAULT_OFFSCREEN_PAGES);
        limit = DEFAULT_OFFSCREEN_PAGES;
    }
    if (limit != mOffscreenPageLimit) {
        mOffscreenPageLimit = limit;
        populate();
    }
}
Concertgoer answered 25/11, 2019 at 16:8 Comment(0)
H
1

Try this it worked for me :

Handler handler = new Handler();
handler.post(new Runnable()
{
    @Override
 public void run()
{
 firstFragment(position);
}
});

for more info check this link :

stackoverflow

Hellbent answered 22/10, 2018 at 14:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.