FragmentManager popBackStack 不删除片段

Posted

技术标签:

【中文标题】FragmentManager popBackStack 不删除片段【英文标题】:FragmentManager popBackStack doesn't remove fragment 【发布时间】:2014-06-23 07:58:38 【问题描述】:

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

当用户更改部分时,我在 fragmentmanager backstack 上调用 pop 直到我到达 Home,然后加载新部分。

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

    加载在 onResume() 上调用 setHasOptionsMenu(true) 的部分 加载另一个部分(它应该从堆栈中取出的旧部分)。我看还行。没有显示菜单 离开应用程序(例如,转到 android Laucher 活动),然后当我返回时,我看到了正确的部分,但它显示的是旧 Fragment 的菜单。

我已经迭代了 backstack 并打印了每个片段,但它不是带有菜单的片段。

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

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

更新:

我正在使用这段代码来加载新的片段

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: 我看到它正在进入我的片段 onDestroy() 方法,因此它应该被销毁。但是我不知道为什么当 Main 活动恢复时它会再次被调用。

【问题讨论】:

你使用 FragmentTransaction.add 还是 FragmentTransaction.replace ? 【参考方案1】:

我发现问题不在于添加和删除堆栈片段的逻辑。

问题是某些片段在其中加载了另一个片段(它具有 ViewPager 组件)。然后我想,当片段被移除时,这些片段也被移除了。

仅当您使用getChildFragmentManager() 方法时才适用。在其他片段中加载片段时必须使用此方法。如果不是,则将片段与片段活动相关联。

【讨论】:

【参考方案2】:

我发现了这个问题,因为在调用之后

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

此代码fragmentManager.getFragments().size() 返回堆栈中的最大片段数。我检查了 null 上的每个片段。而且我发现某些片段在我的情况下是空的。也许它会帮助某人)

【讨论】:

【参考方案3】:

popBackStack 只会恢复您最后的FragmentTransaction

如果你使用FragmentTransaction.addpopBackStack 只会调用FragmentTransacetion.remove

但是如果你打电话给FragmentTransaction.replacepopBackStack 会打电话给FragmentTransaction.removeFragmentTransaction.add

对于您的“注意 1”: FragmentTransaction.replace 不会改变你的片段状态。

【讨论】:

我不想使用替换,因为我有一个无限的 ListView 填充了分页服务。所以如果我看到第 27 项并单击该项目以获取详细信息,当我回来时我想要在进入详细信息部分之前准确查看我所看到的内容。使用 add 很容易实现,因为它不会删除片段,并且在加载细节后使用 pop 可以按预期工作【参考方案4】:

如果您真的想立即删除片段,请执行以下操作: How to replace Fragments of different types?

否则对片段使用替换事务以平滑过渡和无麻烦的方法,请参阅https://***.com/a/23013075/3176433

也了解 Fragment 生命周期, http://developer.android.com/guide/components/fragments.html

【讨论】:

【参考方案5】:

我遇到了类似的问题,popBackStack() 没有删除我的片段。 但是,我注意到我打错了FragmentManager,我必须调用getSupportFragmentMananger() 而不是getFragmentManager()

【讨论】:

【参考方案6】:

android:name="androidx.navigation.fragment.NavHostFragment"app:defaultNavHost="true"app:navGraph="@navigation/nav_graph" 的活动中可能存在<fragment><androidx.fragment.app.FragmentContainerView>

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

【讨论】:

以上是关于FragmentManager popBackStack 不删除片段的主要内容,如果未能解决你的问题,请参考以下文章

无法从 android.app.FragmentManager 转换为 android.support.v4.app.FragmentManager

android.support.v4.app.FragmentManager无法转换为android.app.FragmentManager

在 FragmentManager 中管理 BackStackEntries

从 Fragment (support.v4) 中获取 FragmentManager [重复]

FragmentManager 和 FragmentTransaction 到底是做啥的?

使用 (Child)FragmentManager 正确使用子子片段