FragmentManager popBackStack无法移除片段。

17

我正在使用Fragments实现菜单导航。所以我从主页开始,然后用户可以导航到不同的部分和每个部分的详细信息。

当用户更改部分时,我会在fragmentmanager回退栈上调用pop直到达到主页,然后加载新的部分。

这一切都按预期工作。但我遇到了这个问题:

  1. 加载调用onResume()方法的部分并在其中调用setHasOptionsMenu(true)
  2. 再加载另一个部分(旧部分应该已经从栈中退出)。我看到它没问题。没有菜单显示
  3. 离开应用程序(例如,转到Android Laucher活动),然后当我返回时,我看到正确的部分,但它显示旧Fragment的菜单。

我已经迭代了回退栈并打印了每个片段,那里没有带有菜单的片段。

我在onResume()方法(标记了setHasOptionsMenu(true)的位置)上放了一个调试标记,它确实进入了这里,因此Fragment仍然在某个地方。

我想知道我是否做错了什么,以及如何解决它,谢谢

更新:

我正在使用以下代码加载新的Fragments:

fm.beginTransaction()
    .add(container, sectionFragment.getFragment())
    .addToBackStack(sectionFragment.getFragmentName())
    .commit();

另外,用于删除的代码:

private void clearStack(){
int count = fm.getBackStackEntryCount();
    while(count > 1){
        fm.popBackStack();
        count--;
    }
}
注意1:我使用添加(add)而非替换(replace),因为我不希望在从详细部分导航回来时丢失片段的状态。当我加载另一个不同的部分时,我调用clearStack将堆栈弹出到1,然后加载新的片段。最后,我调用executePendingTransactions()完成从事务中删除片段。 注意2:我发现它正在进入我的fragment onDestroy()方法,所以它应该已经被销毁了。但是我不知道为什么当主Activity恢复时,它又被调用了一次。

你使用 FragmentTransaction.add 还是 FragmentTransaction.replace? - Neige
6个回答

24
我发现问题并不在于堆栈中添加和移除片段的逻辑。
问题是某些片段在其内部加载了另一些片段(其中包含ViewPager组件)。然后我认为,当片段被移除时,这些片段也会被移除。
只有在使用getChildFragmentManager()方法时才是正确的。必须在其他片段中加载片段时使用此方法。否则,片段将与片段活动相关联。

7
我发现这个问题,是因为调用了
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

这段代码 fragmentManager.getFragments().size() 返回了堆栈中最大片段数。我检查了每个片段是否为空。在我的情况下,我发现有些片段是空的。也许这会对其他人有所帮助。请注意保留HTML标记。

7

popBackStack 只会撤销您最后一次的 FragmentTransaction

如果您使用 FragmentTransaction.addpopBackStack 将只调用 FragmentTransacetion.remove

但是,如果您调用 FragmentTransaction.replacepopBackStack 将调用 FragmentTransaction.removeFragmentTransaction.add

对于您的 "NOTE 1": FragmentTransaction.replace 不会改变您的片段状态。


我不想使用replace,因为我有一个由分页服务填充的无限ListView。所以,如果我正在查看第27个项目并单击该项目以获取详细信息,则返回后我希望看到之前查看的内容。使用add很容易实现,因为它不会删除片段,并且在加载详细信息后使用pop可以按预期工作。 - edrian

0

0
我曾经遇到过类似的问题,popBackStack()无法移除我的片段。 但是,我注意到我调用了错误的FragmentManager,我应该调用getSupportFragmentMananger()而不是getFragmentManager()

0

也许在活动中有一个 <fragment><androidx.fragment.app.FragmentContainerView>,它们拥有 android:name="androidx.navigation.fragment.NavHostFragment"app:defaultNavHost="true"app:navGraph="@navigation/nav_graph" 属性。

在这种情况下,导航由 nav_graph 控制。如果您不想使用 NavControllerNavHostFragment,也许应该移除导航并清理 <fragment> 标签。


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