使用方法setOffscreenPageLimit()后,FragmentManager已经在执行事务

时间:2016-10-17 19:17:20

标签: android android-fragments android-viewpager android-tablayout

我有一个带有多个片段的导航抽屉,其中一个是带有两个recyclerview片段的tablayout,在切换导航抽屉片段后,RecyclerView项目消失,我找到了一个解决方案,我需要使用方法setOffscreenPageLimit() ViewPager但它给了我问题标题中提到的错误

这是我的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)

这是标签布局片段代码

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

3 个答案:

答案 0 :(得分:27)

我遇到了与你类似的问题,经过几个小时的研究,我发现了这个问题。 如果在Fragment中创建ViewPager,则需要对FragmentPagerAdapter使用getChildFragmentManager(),而不是getFragmentManager()。

所以你的setupViewPager()方法应该是这样的。

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

问题的根本原因是你在Fragment中嵌入了Fragment,这就是它抛出异常的原因。

java.lang.IllegalStateException: FragmentManager is already executing transactions

根据Google的文档:

  

您现在可以在片段中嵌入片段。这对于a非常有用   您希望放置动态和可重复使用的各种情况   UI组件成为一个自身动态的UI组件   可重复使用。例如,如果使用ViewPager创建片段   您可以左右滑动并占用大部分屏幕空间   现在可以将片段插入每个片段页面。要嵌套片段,   只需在你所在的Fragment上调用getChildFragmentManager()   想要添加一个片段。这将返回您可以使用的FragmentManager   像往常一样使用顶层活动来创建   片段交易。

答案 1 :(得分:0)

尝试一下对我有用:

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

有关更多信息,请检查此链接:

stackoverflow

答案 2 :(得分:0)

我认为真正的答案是在设置适配器之前调用setOffscreenPageLimit,因为在设置适配器之后,ViewPager将开始填充子片段。这就是为什么它将在子片段实例化和设置页面限制之间创建竞争条件的原因。如果页面限制小于默认值,我认为在尝试创建片段时必须销毁一些片段。

解决方案

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

原因

检查ViewPager的源代码,默认的屏幕外页面为1(DEFAULT_OFFSCREEN_PAGES)。用于setOffscreenPageLimit()的任何其他值将触发ViewPager内部的populate()调用。

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