使用片段清除堆栈

biq*_*llo 231 android android-fragments

我将我的Android应用程序移植到了蜂窝状态,然后为了使用碎片我做了一个大的重构.在我之前的版本中,当我按下Home按钮时,我曾经做过一次ACTIVITY_CLEAR_TOP以重置后台堆栈.

现在我的应用程序只是一个包含多个片段的Activity,因此当我按下Home按钮时,我只需替换其中的一个片段.如何清除,而不必使用我的背部栈startActivityACTIVITY_CLEAR_TOP标志?

PJL*_*PJL 408

我在这里贴了类似的东西

来自Joachim的答案,来自Dianne Hackborn:

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

我最后只使用:

FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {    
    fm.popBackStack();
}
Run Code Online (Sandbox Code Playgroud)

但同样可以使用类似的东西:

((AppCompatActivity)getContext()).getSupportFragmentManager().popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)
Run Code Online (Sandbox Code Playgroud)

将弹出所有状态到指定状态.然后,您可以将片段替换为您想要的片段

  • 要转到顶部,只需使用:fragmentManager.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE); (226认同)
  • 对于它的价值,使用fragmentManager.popBackStackImmediate(null,FragmentManager.POP_BACK_STACK_INCLUSIVE); 对我来说效果更好,因为它阻止了片段动画的执行 (52认同)
  • 这不能正常工作 - 它将触发对onStart之间的每个片段的调用 (17认同)
  • 好吧,它等同于按下后退按钮一次或多次,因此它会更改当前可见的片段.(至少我试过的时候) (8认同)
  • 我和彼得有同样的问题.我想清除所有碎片,而不是让它循环通过它们,这有很多含义.例如,您将通过顺序弹出堆栈中的每个片段来命中您不需要的生命周期事件. (6认同)
  • 但这有很大的副作用,不是吗? (2认同)

Mor*_*ard 150

为@Warpzit的评论做出回答,让其他人更容易找到.

使用:

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Run Code Online (Sandbox Code Playgroud)

  • 我相信在使用AppCompatActivity时,最新的v7-appCompat库中已经破坏了以这种方式从后台堆栈弹出所有片段.将我的应用程序更新到最新的v7-appCompat库(21.0.0)并扩展新的AppCompatActivity后,以上述方式弹出片段会在FragmentManager的backstack记录中留下一些片段.我建议不要使用它. (14认同)
  • 可以使用 popBackStackImmediate。 (2认同)

dbm*_*dbm 38

对所有有关各方都给予应有的尊重; 我很惊讶地看到你们中有多少人可以用简单的方法清除整个片段

fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

根据Android文档(关于name论点 - 声称的工作提案中的"null").

如果为null,则仅弹出顶部状态

现在,我确实意识到我对你的特定实现缺乏了解(比如在给定的时间点你在后面的堆栈中有多少条目),但是当我期待一个明确的定义时,我会把所有的钱押在接受的答案上更广泛的设备和供应商的行为:

(供参考,与此一起)

FragmentManager fm = getFragmentManager(); // or 'getSupportFragmentManager();'
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {    
    fm.popBackStack();
}
Run Code Online (Sandbox Code Playgroud)

  • 对我来说不是因为每个**pop**都会将你内部带到每个片段的**onCreateView**.我会在某些资源上收到NPE的地方.但是使用**fm.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);**只是杀死了所有的backstack. (4认同)
  • 关于如何在使用循环弹出时跳过 onCreateView 调用的任何见解? (2认同)

小智 18

接受的答案对我来说还不够.我不得不使用:

FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
    fm.popBackStackImmediate();
}
Run Code Online (Sandbox Code Playgroud)

  • 这是在一个不同的答案中指出的,但只是为了确保它被注意到:如果你像这样在一个循环中弹出整个堆栈,你将触发堆栈开始和结束之间每个 Fragment 的生命周期方法. 在大多数用例中,这种实现很可能会产生意想不到的后果。还值得指出的是,`popBackStackImmediate()` 同步执行事务,这通常是不明智的。 (5认同)

geo*_*ore 16

清除后台没有循环

String name = getSupportFragmentManager().getBackStackEntryAt(0).getName();
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Run Code Online (Sandbox Code Playgroud)

其中name是addToBackStack()参数

getSupportFragmentManager().beginTransaction().
                .replace(R.id.container, fragments.get(titleCode))
                .addToBackStack(name)
Run Code Online (Sandbox Code Playgroud)


Md *_*sin 16

适用于我而不使用循环的简单方法:

 FragmentManager fragmentManager = getSupportFragmentManager();
 //this will clear the back stack and displays no animation on the screen
 fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Run Code Online (Sandbox Code Playgroud)


小智 11

嗨~我找到了一个更好的解决方案,来自:https : //gist.github.com/ikew0ng/8297033

    /**
 * Remove all entries from the backStack of this fragmentManager.
 *
 * @param fragmentManager the fragmentManager to clear.
 */
private void clearBackStack(FragmentManager fragmentManager) {
    if (fragmentManager.getBackStackEntryCount() > 0) {
        FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(0);
        fragmentManager.popBackStack(entry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请扩展您的答案,说明为什么此解决方案更好。 (2认同)

Mar*_*ann 9

对于这里的 kotlin 人:

repeat(supportFragmentManager.backStackEntryCount) {
    supportFragmentManager.popBackStack()
}
Run Code Online (Sandbox Code Playgroud)


Nic*_*cks 8

我只想补充一点: -

使用以下从backstack弹出

fragmentManager.popBackStack()

只是从事务中删除片段,它不会从屏幕上删除片段.理想情况下,它可能不会被您看到,但可能会有两个或三个碎片堆叠在一起,而在背面按键上,UI可能看起来混乱,堆叠.

举一个简单的例子: -

假设你有一个fragmentA,它使用fragmentmanager.replace()加载Fragmnet B 然后我们执行addToBackStack来保存这个事务.所以流程是: -

第1步 - > FragmentA-> FragmentB(我们移动到FragmentB,但片段A在背景中,不可见).

现在你在fragmentB中做了一些工作并按下Save按钮 - 保存之后应该返回到fragmentA.

步骤2->在保存FragmentB时,我们回到FragmentA.

第3步 - >所以常见的错误是...在Fragment B中,我们将使用fragmentA片段管理Manager.replace()fragmentB.

但实际上发生了什么,我们再次加载Fragment A,取代FragmentB.所以现在有两个FragmentA(一个来自STEP-1,一个来自这个STEP-3).

FragmentsA的两个实例相互堆叠,可能不可见,但它就在那里.

因此,即使我们通过上述方法清除了后端堆栈,事务也会被清除,但不是实际的碎片.理想情况下,在这种特殊情况下,按下保存按钮,只需执行fm.popBackStack()fm.popBackImmediate()即可返回fragmentA .

所以正确的Step3-> fm.popBackStack()返回到已经在内存中的fragmentA.