简体   繁体   English

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

[英]Pressing back after getting fragment from backstack crashes app, “Android IllegalStateException Fragment already added”

So I have an activity that holds a MapsFragment and first initializes it without storing it in backstack (if I store it in backstack, pressing back button pops off fragment and leaves empty container, which is not what I want).所以我有一个保存 MapsFragment 并首先初始化它而不将它存储在 backstack 中的活动(如果我将它存储在 backstack 中,按下后退按钮会弹出片段并留下空容器,这不是我想要的)。 this is the code:这是代码:

transaction.replace(mFragmentContainerRes, 
                   MapsFragment.newInstance(), MapsFragment.getClass().getName()).commit();

I then replace it with a ChatRoomFragment like so:然后我用 ChatRoomFragment 替换它,如下所示:

transaction.replace(mFragmentContainerRes, 
                   ChatRoomFragment .newInstance(), ChatRoomFragment .getClass().getName())
                .addToBackStack(ChatRoomFragment .getClass().getName());
                transaction.commit();

So then I have a Navigation Drawer in my main activity, and when the home button is pressed, I retrieve the MapsFragment like so from the backstack:然后我在我的主要活动中有一个导航抽屉,当按下主页按钮时,我像这样从后台检索 MapsFragment :

Fragment fragment = manager.findFragmentByTag(MapFragment.getClass().getName());

 transaction.replace(mFragmentContainerRes, fragment, backStateName).commit();

Now if I press the back button while in the retrieved MapsFragment, the app crashes with this error thrown:现在,如果我在检索到的 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)

For some reason, the Activity is trying to add the MapsFragment again when I press the back button.出于某种原因,当我按下后退按钮时,Activity 试图再次添加 MapsFragment。 Why is this?这是为什么? How can I fix this?我该如何解决这个问题?

According to my research, this usually happens if you .add instead of .replace, but I am calling .replace everywhere on my Fragment transactions.根据我的研究,如果您使用 .add 而不是 .replace,这通常会发生,但我在 Fragment 事务中到处都调用 .replace。

Solved this issue by popping my entire backstack when wanting to return to the home fragment instead of replacing the current fragment with the home fragment:当想要返回主片段而不是用主片段替换当前片段时,通过弹出我的整个 backstack 解决了这个问题:

            getSupportFragmentManager().popBackStack(null,
                    FragmentManager.POP_BACK_STACK_INCLUSIVE);

The fragment backstack just stores FragmentTransactions, not actual fragments. Fragment backstack 只存储 FragmentTransactions,而不是实际的 Fragment。 And when it's popped when you click back, it simply reverses this transaction as it got it.当您单击返回时弹出它时,它只会在收到此交易时撤消该交易。 So in your case you load ChatRoomFragment with replace, which is the same as removing all fragments and adding ChatRoomFragment.因此,在您的情况下,您使用替换加载 ChatRoomFragment,这与删除所有片段并添加 ChatRoomFragment 相同。 So the FragmentTransaction going forward is [1 - Remove MapsFragment, 2 - Add ChatRoomFragment] .所以[1 - Remove MapsFragment, 2 - Add ChatRoomFragment]的 FragmentTransaction 是[1 - Remove MapsFragment, 2 - Add ChatRoomFragment] This is the FragmentTransaction and is executed and now you're on ChatRoomFragment.这是 FragmentTransaction 并被执行,现在您在 ChatRoomFragment 上。 If you popBackStack now, it works like it should.如果你现在popBackStack ,它会像它应该的那样工作。 The transaction is reversed and ChatRoomFragment is removed and MapsFragment is added.事务被撤销,ChatRoomFragment 被删除,MapsFragment 被添加。

When you click the Home button on the NavDrawer, you replace MapsFragment, which is the same as removing ChatRoomFragment and adding MapsFragment.当您单击 NavDrawer 上的 Home 按钮时,您将替换 MapsFragment,这与移除 ChatRoomFragment 并添加 MapsFragment 相同。 Note this transaction isn't added to the backstack so the current backstack is still [1 - Add MapsFragment, 2 - Remove ChatRoomFragment] , the reverse of the initial FragmentTransaction in the previous paragraph.请注意,此事务未添加到 backstack,因此当前 backstack 仍然是[1 - Add MapsFragment, 2 - Remove ChatRoomFragment] ,与上一段中的初始 FragmentTransaction 相反。 The stupid backstack doesn't know you replaced MapsFragment and it's the current fragment so when you click the back button now, it just executes the current backstack and tries to add the MapsFragment again and you get that Fragment already added error.愚蠢的 backstack 不知道您替换了 MapsFragment 并且它是当前片段,因此当您现在单击后退按钮时,它只会执行当前的 backstack 并尝试再次添加 MapsFragment 并且您会收到Fragment already added错误。

Your selected solution works because you're simply popping the backstack when a user clicks the Home button on the NavDrawer and the backstack is clear now.您选择的解决方案有效,因为当用户单击 NavDrawer 上的 Home 按钮时,您只是弹出 backstack,并且 backstack 现在清晰。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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