繁体   English   中英

从 backstack 获取片段后按回崩溃应用程序,“Android IllegalStateException Fragment already added”

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM