131

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

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

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

现在我已经扩展了片段e以包含一个按钮,该按钮e1也可以在详细信息窗格中加载另一个片段。我在 fragmente的 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();
}

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

4

7 回答 7

258

好吧,有几种方法可以解决这个问题,具体取决于预期的行为,但是这个链接应该给你所有最好的解决方案,毫不奇怪来自 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),
于 2011-05-12T21:48:43.087 回答
62

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

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

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

于 2013-07-24T09:58:10.507 回答
28

感谢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();

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

} /* end of for */
于 2012-11-09T07:47:03.940 回答
7

为了清理Backstack,我研究了很多,终于看到了Transaction BackStack及其管理。这是最适合我的解决方案。

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

上述方法循环遍历 backstack 中的所有事务,并立即一次删除它们。

注意:上面的代码有时不起作用,因为这个代码我面临ANR,所以请不要尝试这个。

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

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack("name",FragmentManager.POP_BACK_STACK_INCLUSIVE);
  • name 如果非空,这是要查找的先前返回状态的名称;如果找到,将弹出该状态之前的所有状态。这
  • POP_BACK_STACK_INCLUSIVE 标志可用于控制命名状态本身是否被弹出。如果为 null,则仅弹出顶部状态。
于 2015-06-19T06:46:06.940 回答
3

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

FragmentManager manager = getFragmentManager();
while (manager.getBackStackEntryCount() > 0){
        manager.popBackStackImmediate();
    }
于 2016-02-29T16:17:56.560 回答
0

正如在How to pop fragment off backstackLarsH在这里所写的那样,我们可以使用这种方法从上到下弹出几个片段到特定的标签(连同标记的片段):

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

用您的片段标签替换“片段”。请记住,首先我们应该将片段添加到 backstack:

fragmentTransaction.addToBackStack("frag")

如果我们用 来添加片段addToBackStack(null),我们就不会那样弹出片段。

于 2019-12-03T13:29:59.423 回答
-4
    // pop back stack all the way
    final FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
    int entryCount = fm.getBackStackEntryCount(); 
    while (entryCount-- > 0) {
        fm.popBackStack();
    }
于 2013-03-05T21:10:37.510 回答