【问题标题】:How to clear backStack of support FragmentManager?如何清除支持FragmentManager的backStack?
【发布时间】:2024-01-16 02:29:01
【问题描述】:

有什么办法,如何在存储的片段中不调用 onCreateView() 清除支持 FragmentManager 的 backStack?

我了解片段生命周期并在弹出时调用 onDestroyView() 和 onCreateView()。 http://developer.android.com/guide/components/fragments.html#Creating

我也知道如何从 backstack 中弹出所有片段

mFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

for(int i = 0; i < mFragmentManager.getBackStackEntryCount(); ++i) {            
     mFragmentManager.popBackStack();
}

但两种方式都调用 onCreateView() 和其他生命周期方法,直到 onDestroyView() 和 onDestroy()。

但是有什么办法,如何清除这个 backstack,只从 onDestroyView() 调用而不是从 onCreateView()(片段内部)调用?

或者有什么办法可以用清除以前的片段来替换事务?

例如,我想在进行交易之前明确回溯:

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentManager.beginTransaction().replace(R.id.content, fragment).commit();

【问题讨论】:

  • 您的目标是避免在片段视图从堆栈中弹出时重新创建它们,因为您知道当弹出完成时,最终片段状态将被“销毁”?
  • 是的,这正是我想要的
  • 万一,你能解决这个问题吗?我现在在做单活动架构时遇到了同样的问题。
  • @EdwinMartinez 不是真的。我所做的(我并不为此感到自豪),活动中的“cleaningBackstack”属性的丑陋解决方法。所以活动中的代码如下所示:```cleaningBackstack = true; fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); fragmentManager.executePendingTransactions(); cleanBackstack = false; ``` 并在 onViewCreated 片段中: ``` if (a.isCleaningBackstack()) return; ```

标签: android android-fragments back-stack fragmenttransaction fragment-backstack


【解决方案1】:

我还没有找到解决这个问题的简单方法。我几乎可以肯定FragmentManagerFragment 没有任何功能可以让您控制从堆栈中弹出片段时调用哪个生命周期方法。我将概述两种可能的方法。每个都有一些不受欢迎的方面。

第一种方法假设您从后台堆栈中弹出的片段是活动的子项。如果它们是片段的子级,则该方法仍然适用,只是父对象类型不同。

使用 getter 方法将布尔成员 mClearingBackStack 添加到活动(或父片段)。 only 在您开始完全清除后台堆栈时设置布尔值。在要禁用处理的片段生命周期方法中,获取标志并相应地修改处理。对于onCreateView()onDestroyView(),片段将被附加,主机活动可通过getActivity() 获得。将其转换为您的活动类以使用标志的 getter 方法。

因为popBackStack() 是异步的,所以必须在堆栈展开完成后才能清除标志。我还没有尝试过,但我认为在调用popBackStack() 清除标志之后发布Runnable 应该可以。因为 Runnable 需要排在队列的末尾,所以必须使用 View.post() 而不是 Activity.runOnUiThread()。另一种方法是调用executePendingTransactions() 等待堆栈展开完成。

第二种方法更简洁,如果您的设计可以容纳它。创建一个占位符片段,它是您的活动的子片段和所有其他片段的父片段。对于您现在拥有的所有片段事务,使用新片段的FragmentManager,使用getChildFragmentManager() 获得。当您想清除所有这些事务时,不要弹出子片段管理器的堆栈,而是删除或替换活动片段管理器中的父片段。当父片段被移除时,它的所有子片段都被销毁并经历拆解步骤,onDestroyView()、onDestroy() 等.这种方法比第一种更简单且更易于维护,但需要您重新设计片段层次结构。这种方法的另一个问题是您必须添加一些代码来处理带有片段层次结构的 Back 操作。问题和各种解决方案描述here

【讨论】: