从backstack获取片段后按回来崩溃应用程序," Android IllegalStateException片段已添加"

时间:2017-10-22 02:14:19

标签: java android android-layout android-fragments android-activity

所以我有一个包含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();

然后我在我的主要活动中有一个导航抽屉,当按下主页按钮时,我从backstack中检索这样的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,这通常会发生,但我在片段交易中到处都是.replace。

2 个答案:

答案 0 :(得分:1)

当想要返回到主片段而不是用主片段替换当前片段时,通过弹出我的整个backstack解决了这个问题:

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

答案 1 :(得分:0)

片段堆栈仅存储FragmentTransactions,而不是实际的片段。当您单击返回时弹出它时,它会简单地逆转此事务。因此,在您的情况下,您将使用replace加载ChatRoomFragment,这与删除所有片段并添加ChatRoomFragment相同。因此前进的FragmentTransaction是[1 - Remove MapsFragment, 2 - Add ChatRoomFragment]。这是FragmentTransaction,已执行,现在您位于ChatRoomFragment。如果现在popBackStack,它会像应该的那样工作。事务被撤消,删除ChatRoomFragment并添加MapsFragment。

单击NavDrawer上的“主页”按钮时,将替换MapsFragment,这与删除ChatRoomFragment和添加MapsFragment相同。请注意,该事务未添加到Backstack中,因此当前Backstack仍为[1 - Add MapsFragment, 2 - Remove ChatRoomFragment],与上一段中的FragmentTransaction初始相反。愚蠢的堆栈并不知道您替换了MapsFragment,而是当前的片段,因此,当您现在单击“后退”按钮时,它只是执行当前的堆栈,并尝试再次添加MapsFragment并收到该Fragment already added错误。

您选择的解决方案之所以有效,是因为当用户单击NavDrawer上的“主页”按钮时,您只是在弹出后退堆栈,而后退堆栈现在已清除。