当离开一个深度嵌套的堆栈时,这是清理碎片回堆栈的正确方法吗?

我使用 Android 兼容性库来实现片段,并扩展了布局示例,以便片段包含一个按钮,该按钮会触发另一个片段。

在左边的选择面板中,我有5个可选项目 -A B C D E

每个都在详细信息窗格 -a b c d e中加载一个片段(通过 FragmentTransaction:replace)

现在我已经扩展了片段 e,以包含一个按钮,该按钮在细节窗格中加载另一个片段 e1。我在片段 e的 onClick 方法上做了以下工作:

FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.replace(R.id.details_frag, newFrag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();

如果我作出以下选择:

E - e - e1 - D - E

然后片段 e在详细信息窗格中。这很好,我想要的。然而,如果我按下 back按钮在这一点上它什么也不做。我必须点击它两次,因为 e1仍然在堆栈上。此外,在点击之后,我在 onCreateView 中得到了一个 null 指针异常:

为了“解决”这个问题,我在选择 A B C D E时添加了以下内容:

FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
fm.popBackStack();
}

只是想知道这是否是正确的解决方案,或者我是否应该做一些不同的事情?

145749 次浏览

有几种方法可以根据预期的行为来做到这一点,但是这个链接应该会给你所有最好的解决方案,毫无疑问是来自 Dianne Hackborn 的

Http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42

实际上,您有以下选项

  • 使用初始回退堆栈状态的名称并使用 PopBackStack (字符串名, POP _ Back _ STACK _ INclusIVE) .
  • 使用 FragmentManager.getBackStackEntryCount()/getBackStackEntryAt().getId() 检索回栈中第一个条目的 ID,并且 PopBackStack (int id, POP _ Back _ STACK _ INclusIVE) .
  • 应该可以打开整个后面的堆栈... ... 我认为文档 这是不对的。(实际上我想这并不包括 你通过 POP_BACK_STACK_INCLUSIVE) ,

由于 约阿希姆的答案,我使用的代码来清除所有的回栈条目最后。

// In your FragmentActivity use getSupprotFragmentManager() to get the FragmentManager.


// Clear all back stack.
int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
for (int i = 0; i < backStackCount; i++) {


// Get the back stack fragment id.
int backStackId = getSupportFragmentManager().getBackStackEntryAt(i).getId();


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


} /* end of for */
    // pop back stack all the way
final FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
int entryCount = fm.getBackStackEntryCount();
while (entryCount-- > 0) {
fm.popBackStack();
}

另一个干净的解决方案,如果你不想弹出所有堆栈条目..。

getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().beginTransaction().replace(R.id.home_activity_container, fragmentInstance).addToBackStack(null).commit();

这将首先清理堆栈,然后加载一个新的片段,因此在任何给定的点上,堆栈中都只有一个片段

我已经研究了很多关于清理背包,最后看到 事务回溯及其管理。这是对我最有效的解决方案。

 // CLEAR BACK STACK.
private void clearBackStack() {
final FragmentManager fragmentManager = getSupportFragmentManager();
while (fragmentManager.getBackStackEntryCount() != 0) {
fragmentManager.popBackStackImmediate();
}
}

上面的方法循环遍历回栈中的所有事务,并立即一次删除一个事务。

注意: 以上代码有时不工作,我面对 ANR因为这个代码,所以请不要尝试这一点。

更新 下面的方法从回栈中删除该“名称”的所有片段。

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack("name",FragmentManager.POP_BACK_STACK_INCLUSIVE);
  • Name 如果非空,则为以前的返回状态的名称 查找; 如果找到,则弹出该状态之前的所有状态
  • POP _ Back _ STACK _ INclusIVE 标志可用于控制是否弹出命名状态本身。如果为空,则只弹出顶部状态。

我使用的代码与使用 while 循环的代码相似,但是我在每个循环中调用条目计数... ... 所以我认为它有点慢

FragmentManager manager = getFragmentManager();
while (manager.getBackStackEntryCount() > 0){
manager.popBackStackImmediate();
}

正如用 如何从堆栈中弹出片段和这里的 LarsH所写的,我们可以使用这种方法从上到下弹出几个片段到特定的标记(还有带标签的碎片) :

fragmentManager?.popBackStack ("frag", FragmentManager.POP_BACK_STACK_INCLUSIVE);

用你的片段标签代替“片段”。请记住,首先我们应该用以下方法将片段添加到回栈中:

fragmentTransaction.addToBackStack("frag")

如果我们用 addToBackStack(null)添加片段,就不会以这种方式弹出片段。