我有一个托管两个片段的活动。活动开始时会在加载对象时显示加载程序。然后通过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和tabs。 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.FragmentManagerImpl.execSingleAction(FragmentManager.java:1620) 在 v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:637) 在 v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143) 在v4.view.ViewPager.populate(ViewPager.java:1235) 在v4.view.ViewPager.populate(ViewPager.java:1083) 在 v4.view.ViewPager.setOffscreenPageLimit(ViewPager.java:847)
数据显示是否已移除setOffscreenPageLimit(...);
。还有另一种方法可以避免这个问题吗?
在生命周期中,片段事务是否已完成,以便我可以等待设置寻呼机?
答案 0 :(得分:136)
只需在childFragmentManger()
viewpager
Fragment
mPagerAdapter = new ScreenSlidePagerAdapter(getChildFragmentManager());
mPager.setAdapter(mPagerAdapter);
答案 1 :(得分:38)
我在快速替换2个片段并使用executePendingTransactions()时遇到此异常。没有这称呼,没有例外。
我的情况是什么? 我打开一个片段A并在其onResume()中(在一个条件下)我要求活动用片段B替换片段。此时发生异常。
我的解决方案是使用Handler.post(runnable),它将查询放在线程队列的末尾而不是立即运行它。这样我们就可以确保在完成任何先前的交易之后执行新的交易。
所以我的解决方案很简单:
Handler uiHandler = new Handler();
uiHandler.post(new Runnable()
{
@Override
public void run()
{
openFragmentB(position);
}
});
答案 2 :(得分:25)
如果您定位sdk 24及以上版本,则可以使用:
FragmentTransaction.commitNow()
而不是commit()
如果您要定位旧版本,请尝试致电:
FragmentManager.executePendingTransactions()
致电commit()
答案 3 :(得分:4)
我遇到了同样的问题。但是,我使用的是仅获取 FragmentStateAdapter
的 FragmentActivity
构造函数:
package androidx.viewpager2.adapter;
public FragmentStateAdapter(
@NonNull FragmentActivity fragmentActivity
) {
this(fragmentActivity.getSupportFragmentManager(), fragmentActivity.getLifecycle());
}
即使它从 fragmentActivity
实例获取生命周期,它也根本不起作用。
然后,深入研究 FragmentStateAdapter
的代码,我看到还有另一个构造函数,您可以在其中传递 Lifecycle 实例。
package androidx.viewpager2.adapter;
public FragmentStateAdapter(
@NonNull FragmentManager fragmentManager,
@NonNull Lifecycle lifecycle
) {
mFragmentManager = fragmentManager;
mLifecycle = lifecycle;
super.setHasStableIds(true);
}
因此,我更改了 PageAdapter
构造函数以接收 FragmentManager
作为 childFragmentManager
和来自 viewLifecycleOwner
的 LifeCycle。并将这些参数传递给 FragmentStateAdapter
构造函数:
class MyPagerAdapter(
fragmentManager: FragmentManager,
lifecycle: Lifecycle
) : FragmentStateAdapter(fragmentManager, lifecycle) {
//...
}
然后,当调用我的 PagerAdapter 构造函数时,我传递了 FragmentManager 和
我从 viewLifecycleOwner
获取生命周期:
val myPagerAdapter = MyPagerAdapter(
fragmentManager = childFragmentManager,
lifecycle = viewLifecycleOwner.lifecycle
)
[更新] MyPagerAdapter 是从 Fragment 设置的。
答案 4 :(得分:2)
如果有人使用Robolectric> 3.6并至少通过ViewPager使用4.0.2,则即使使用正确的代码,您也可能会看到它。
this github issue中有相关信息跟踪Robolectric的问题。
在我撰写此答案时,问题仍未解决,唯一已知的解决方法是使用@Config(sdk = {27}),该方法似乎对某些用户有效,但对我不起作用,或者使用以下命令实现ViewPagerShadow在测试包中有一个变通方法,其中包含在github上引用的相当长的代码(如果更好,我可以在此处包括它,但这可能不足以作为答案?)并使用@Config(shadows = {ShadowViewPager.class})< / p>
答案 5 :(得分:1)
我遇到了类似的问题,
添加片段A的mainAcitivity。
然后使用fragmentA回调mainactivity将自身替换为fragmentB。
当用fragmentB替换并提交事务时,MainActivity抛出异常“ fragmentmanager已经执行事务”。
问题实际上来自fragmentB。
我在片段B中有一个TabHost,它需要getfragmentmanager()来添加tabfragment。
用fragmentB中的getchildfragmentmanager()替换getfragmentmanager()解决了这个问题。
答案 6 :(得分:1)
这是 <exclude-pattern type="relative">^(?!plugins/(arve-|advanced-re|edd-)).+</exclude-pattern>
时代的一个相当古老的答案,并帮助许多遇到此问题的人解决了这个问题。以防万一您遇到 ViewPager
并面临类似问题,
我们知道,当片段中有 ViewPager2
并且 ViewPager2
类具有带 FragmentStateAdapter
参数的构造函数时会发生这种情况,因此您可以使用它来创建适配器。
喜欢
Fragment
那么,
class ScreenSlidePagerAdapter(fragment: Fragment): FragmentStateAdapter(fragment)
答案 7 :(得分:0)
我使用{
"id" : "BNK007596994",
"name" : "Live_HD",
"metadataSet" : {
"description" : "Live Template",
"type" : "Live"
}
"features" : "HD"
}
而不是Sub Macro9()
'
' Macro9 Macro
'
'
Range("A3").Select
Selection.Copy
Range("A2").Select
ActiveSheet.Paste
Range("B2").Select
Application.CutCopyMode = False
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = "=+SUM(R[1]C:R[3]C)"
Range("B2").Select
Selection.Copy
Range("B3").Select
Selection.End(xlToRight).Select
Range("S2").Select
Range(Selection, Selection.End(xlToLeft)).Select
ActiveSheet.Paste
Selection.End(xlToLeft).Select
Range(Selection, Selection.End(xlToRight)).Select
Application.CutCopyMode = False
Selection.Copy
Windows("Final.xlsx").Activate
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False
Range("A6").Select
Windows("copy.xlsm").Activate
Rows("2:2").Select
Range(Selection, Selection.End(xlDown)).Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Selection.End(xlToLeft).Select
End Sub
扩展了适配器,这解决了我的问题。
如果片段是动态的并且在运行时频繁变化,请使用FragmentStatePagerAdapter
。
如果片段是静态的,并且在运行时不会频繁更改,请使用FragmentPagerAdapter
。
本文的启发, https://medium.com/inloopx/adventures-with-fragmentstatepageradapter-4f56a643f8e0
答案 8 :(得分: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)
}
}