从后退堆栈中弹出而不添加到后退堆栈时,找不到ID对应的视图。

4
我正在开发一个Android应用程序,遇到了涉及片段和片段事务的错误。我创建了一个示例应用程序来演示问题。这是我在做什么:
  1. Fragment1添加到fragmentSpace中,不添加到返回堆栈。
  2. 使用"beginning"作为返回堆栈的标识,将fragmentSpace替换为Fragment2,并将其添加到返回堆栈中。
  3. Fragment3添加到Fragment2内部的fragmentSpace2中,不添加到返回堆栈。
  4. 使用null作为返回堆栈的标识,将fragmentSpace2替换为Fragment4,并将其添加到返回堆栈中。
  5. 调用getFragmentManager().popBackStack("beginning", FragmentManager.POP_BACK_STACK_INCLUSIVE);尝试撤消所有事务,这应该使用户只能看到Fragment1
然而,在第5步应用程序崩溃,并显示以下错误:
java.lang.IllegalArgumentException: No view found for id 0x7f090004 (me.MitchT.testfragmenttransactions:id/fragmentSpace2) for fragment Fragment3{7f35cb6 #2 id=0x7f090004}
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:886)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
            at android.app.BackStackRecord.popFromBackStack(BackStackRecord.java:1645)
...

我发现如果将步骤3添加到后退栈中,步骤5不再导致应用程序崩溃,也不会出现错误。为什么?

我添加步骤3到后退栈的问题是,我希望用户在添加Fragment3后能够按返回按钮并返回到Fragment1。如果我将其添加到后退栈中,那么当用户按下返回按钮时,它会删除Fragment3,但Fragment2仍然可见,所以他们必须再次按下返回按钮。我试图避免这种双重返回按钮行为。

我觉得没有必要在这个问题上发布示例应用程序中每个文件的代码,因此我创建了一个gist.

所以我的问题是:

  1. 为什么会出现这个错误?
  2. 为什么在将步骤3添加到后退栈后我不再出现错误?
  3. 是否有更好的方法“回到开头”或一次返回两个片段?

谢谢!


找不到ID为beginning的视图。只需使用popbackstack()即可。 - Raghunandan
1个回答

2
据我理解,您有一个片段布局作为活动的容器。
活动托管Fragment1。然后您将Fragment 1替换为添加到返回栈中的Fragment 2。
此时,单击返回按钮会弹出fragment2,并显示托管fragment1的活动。
Fragment2具有包含Fragment3的FrameLayout。然后您将Fragment4替换为添加到返回堆栈中的Fragment3。
现在单击按钮,可以使用getFragmentManager().popBackStack()方法。但是没有带有该id的视图。
只需使用popBackStack()方法。Fragment4 --> Fragment2(托管Fragment3) --> Fragment1(由活动托管)。
如果要将Fragment4添加到托管Fragment1的Activity中,请不要将Fragment4添加到返回堆栈中。
注意:如果要使用嵌套片段,您需要使用getChildFragmentManager()方法。请参阅https://developer.android.com/about/versions/android-4.2.html 还请注意评论部分中的讨论以及op发布的链接Is this the right way to clean-up Fragment back stack when leaving a deeply nested stack?

@MitchTalmadge 但是你在堆栈中有 fragment4。 - Raghunandan
@MitchTalmadge 还需要注意的是,fragment2在后台堆栈中,而fragment3和4则由fragment2托管。 - Raghunandan
@MitchTalmadge 当你使用fragment2替换fragment1时,请尝试相同的操作,它不起作用。还要注意它是嵌套片段。仍在阅读你发布的链接。 - Raghunandan
如果您需要嵌套片段,应该使用 getChildFragmentManager()。只需尝试保留之前的代码即可。http://developer.android.com/intl/ko/about/versions/android-4.2.html - Raghunandan
1
太好了!问题解决了!非常感谢!!我之前不知道getChildFragmentManager(),现在理解了很多。谢谢! - Mitch Talmadge
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接