[英]Pressing back after getting fragment from backstack crashes app, “Android IllegalStateException Fragment already added”
所以我有一个保存 MapsFragment 并首先初始化它而不将它存储在 backstack 中的活动(如果我将它存储在 backstack 中,按下后退按钮会弹出片段并留下空容器,这不是我想要的)。 这是代码:
transaction.replace(mFragmentContainerRes,
MapsFragment.newInstance(), MapsFragment.getClass().getName()).commit();
然后我用 ChatRoomFragment 替换它,如下所示:
transaction.replace(mFragmentContainerRes,
ChatRoomFragment .newInstance(), ChatRoomFragment .getClass().getName())
.addToBackStack(ChatRoomFragment .getClass().getName());
transaction.commit();
然后我在我的主要活动中有一个导航抽屉,当按下主页按钮时,我像这样从后台检索 MapsFragment :
Fragment fragment = manager.findFragmentByTag(MapFragment.getClass().getName());
transaction.replace(mFragmentContainerRes, fragment, backStateName).commit();
现在,如果我在检索到的 MapsFragment 中按下后退按钮,应用程序会崩溃并抛出以下错误:
java.lang.IllegalStateException:
Fragment already added: MapsFragment{e34dc65 #0 id=0x7f0f00b4 com.MapsFragment}
at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1882)
at android.support.v4.app.BackStackRecord.executePopOps(BackStackRecord.java:825)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2577)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:851)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:794)
at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:174)
at com.main.MainActivity.onBackPressed(MainActivity.java:111)
出于某种原因,当我按下后退按钮时,Activity 试图再次添加 MapsFragment。 这是为什么? 我该如何解决这个问题?
根据我的研究,如果您使用 .add 而不是 .replace,这通常会发生,但我在 Fragment 事务中到处都调用 .replace。
当想要返回主片段而不是用主片段替换当前片段时,通过弹出我的整个 backstack 解决了这个问题:
getSupportFragmentManager().popBackStack(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
Fragment backstack 只存储 FragmentTransactions,而不是实际的 Fragment。 当您单击返回时弹出它时,它只会在收到此交易时撤消该交易。 因此,在您的情况下,您使用替换加载 ChatRoomFragment,这与删除所有片段并添加 ChatRoomFragment 相同。 所以[1 - Remove MapsFragment, 2 - Add ChatRoomFragment]
的 FragmentTransaction 是[1 - Remove MapsFragment, 2 - Add ChatRoomFragment]
。 这是 FragmentTransaction 并被执行,现在您在 ChatRoomFragment 上。 如果你现在popBackStack
,它会像它应该的那样工作。 事务被撤销,ChatRoomFragment 被删除,MapsFragment 被添加。
当您单击 NavDrawer 上的 Home 按钮时,您将替换 MapsFragment,这与移除 ChatRoomFragment 并添加 MapsFragment 相同。 请注意,此事务未添加到 backstack,因此当前 backstack 仍然是[1 - Add MapsFragment, 2 - Remove ChatRoomFragment]
,与上一段中的初始 FragmentTransaction 相反。 愚蠢的 backstack 不知道您替换了 MapsFragment 并且它是当前片段,因此当您现在单击后退按钮时,它只会执行当前的 backstack 并尝试再次添加 MapsFragment 并且您会收到Fragment already added
错误。
您选择的解决方案有效,因为当用户单击 NavDrawer 上的 Home 按钮时,您只是弹出 backstack,并且 backstack 现在清晰。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.