这是在离开深层嵌套堆栈时清理Fragment堆栈的正确方法吗?

时间:2011-04-27 09:45:54

标签: android android-fragments fragment-backstack

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

在左侧的选择窗格中,我有5个可选项 - A B C D E

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

现在我扩展了片段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中得到了一个空指针异常:

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

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

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

7 个答案:

答案 0 :(得分:246)

根据预期的行为,有几种方法可以解决这个问题,但是此链接应该为您提供所有最佳解决方案,并且不出意外地来自Dianne Hackborn

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

基本上你有以下选择

  • 使用名称作为初始后备堆栈状态并使用 FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)
  • 使用FragmentManager.getBackStackEntryCount() / getBackStackEntryAt().getId() 检索后栈上第一个条目的ID,和 FragmentManager.popBackStack(int id, FragmentManager.POP_BACK_STACK_INCLUSIVE)
  • FragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) 应该弹出整个后台堆栈...我认为文档 那是错的。 (其实我猜它只是不包括在哪里 你传入POP_BACK_STACK_INCLUSIVE),

答案 1 :(得分:60)

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

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

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

答案 2 :(得分:25)

感谢Joachim回答,我最后使用代码清除所有后台堆栈条目。

// 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();

    fm.popBackStack(backStackId, FragmentManager.POP_BACK_STACK_INCLUSIVE);

} /* end of for */

答案 3 :(得分:7)

我已经研究了很多清理Backstack,最后看到Transaction BackStack and its management。这是最适合我的解决方案。

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

上述方法遍历backstack中的所有事务,并一次一个地删除它们。

注意:以上代码有时无法正常工作,因为此代码,我面临ANR,所以请不要尝试此操作。

<强>更新 下面的方法从backstack中删除该“name”的所有fregment。

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack("name",FragmentManager.POP_BACK_STACK_INCLUSIVE);
  • name如果为非null,则为先前后退状态的名称 寻找;如果找到,将弹出所有达到该状态的状态。在
  • POP_BACK_STACK_INCLUSIVE标志可用于控制是否弹出命名状态本身。如果为null,则仅弹出顶部状态。

答案 4 :(得分:3)

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

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

答案 5 :(得分:0)

How to pop fragment off backstack和@LarsH所述,我们可以使用以下方法从上至下弹出几个片段到特定标签(连同已标记的片段):

for i in listt:
    if not i:
        continue
    if i[0] == 'U':
        print "U is:"
        print i[1]

用片段的标签替换“ frag”。请记住,首先我们应该使用以下命令将片段添加到后堆栈:

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

如果我们使用fragmentTransaction.addToBackStack("frag") 添加片段,则不会以这种方式弹出片段。

答案 6 :(得分:-4)

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