FragmentManager已经在执行事务。提交后何时安全初始化寻呼机?


77

我有一个托管两个片段的活动。该活动首先显示在加载对象时的加载器。然后,通过newInstance方法将加载的对象作为参数传递给两个片段,并附加这些片段。

final FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.replace(R.id.container1, Fragment1.newInstance(loadedObject));
trans.replace(R.id.container2, Fragment2.newInstance(loadedObject));
trans.commit();

第二个片段包含android.support.v4.view.ViewPager和标签。onResume我们将其初始化如下

viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(adapter.getCount()); //the count is always < 4
tabLayout.setupWithViewPager(viewPager);

问题是android然后抛出

java.lang.IllegalStateException:FragmentManager已经在执行事务

使用此堆栈跟踪:(为简洁起见,android.support从软件包名称中取出)

v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143)的v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:637)的v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1620)在v4.view.ViewPager .populate(ViewPager.java:1235)at v4.view.ViewPager.populate(ViewPager.java:1083)at v4.view.ViewPager.setOffscreenPageLimit(ViewPager.java:847)

数据显示是否setOffscreenPageLimit(...);已删除。还有另一种方法可以避免此问题?

在生命周期中何时完成碎片交易,以便我可以等待设置寻呼机?


2
显然,AndroidViewPager会将寻呼机NullPointerExceptiononCreateView的片段内部提升为IllegalStateException : FragmentManager is already executing transactions...以防万一有人掉下来并需要知道
Lovis,2016年

Answers:


30

如果您定位的是sdk 24及更高版本,则可以使用:

FragmentTransaction.commitNow()

代替 commit()

如果您要定位较早的版本,请尝试致电:

FragmentManager.executePendingTransactions()

致电后 commit()


21
FragmentManager.executePendingTransactions()也会导致异常,因为在其代码中调用了execPendingActions()-> sureExecReady(true)-> if(mExecutingActions){ ; }
user2924714 '17

13
这对我不起作用。两种方法均显示崩溃:java.lang.IllegalStateException:FragmentManager已经在执行事务
thalissonestrela

commitNow和addToBackStack的使用也失败了:(
Narendra

204

只需childFragmentManger()viewpager内部使用Fragment

mPagerAdapter = new ScreenSlidePagerAdapter(getChildFragmentManager());
mPager.setAdapter(mPagerAdapter);

18
杜德!你救了我的一天!:D非常感谢!我使用的是嵌套片段,而您的“ getChildFragmentManager”技巧就像魅力一样!^ _ ^
Vivek Solanki

6
这在“返回”(通过“后退”按钮)到活动/片段组合崩溃的情况下也起作用。好决定。
贾斯汀

1
简单而出色的解决方案,节省您的时间,谢谢。
vishva vijay

谢谢!!当我使用“应用更改”和“重新启动活动”作为运行按钮时,我的应用程序崩溃了。
user1090751's

56

快速替换2个片段并使用executePendingTransactions()时出现此异常。没有调用它,也不例外。

我的情况是什么?我打开一个片段A,并在其onResume()中(在一定条件下)要求活动将片段替换为片段B。这时发生异常。

我的解决方案是使用Handler.post(runnable)将查询放在线程队列的末尾,而不是立即运行它。这样,我们确保在完成任何先前的事务后将执行新事务。

所以我的解决方案很简单:

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

2
简单有效。我虽然使用了postDelayed。在我的用例中,它甚至更好,因为初始化阶段正在进行很多工作
gorodechnyj

1
这行得通,但我想知道这如何在内部解决问题?
大卫

7

我有一个类似的问题,

一个主活动添加片段A。

然后,fragmentA回调mainactivity将自己替换为fragmentB。

当用fragmentB替换并提交事务时,MainActivity抛出异常“ fragmentmanager已经执行事务”。

问题实际上来自fragmentB。

我在片段B中有一个TabHost,它需要getfragmentmanager()添加标签片段。

用fragmentB中的getchildfragmentmanager()替换getfragmentmanager()可解决此问题。


2

如果有人使用Robolectric> 3.6并至少通过ViewPager使用4.0.2,则即使使用正确的代码,您也可能会看到它。

此github问题中有相关信息,跟踪Robolectric的问题。

在我编写此答案时,该问题仍未解决,唯一已知的解决方法是使用@Config(sdk = {27}),该方法似乎对某些用户有效,但对我不起作用,或者使用您的替代方法实现ViewPagerShadow测试程序包,其中包含在github上引用的相当长的代码(如果更好,我可以在此处包括它,但这可能不足以作为答案?)并使用@Config(shadows = {ShadowViewPager.class})



0

遇到了一个与问题无关的类似错误,但希望在使用Firebase时它能对某人有所帮助。从.addSnapshotListener()中删除活动,requireActivity或此项,将其保留为空白。

 videosListener = videosCollectionRef
            .addSnapshotListener() { snapshot, exception ->

                if (exception != null) {
                    Log.e("Exception", "Could not retrieve documents: $exception")
                }

                if (snapshot != null) {
                    parseData(snapshot)
                }
            }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.