首页 > 解决方案 > 即使调用了 disallowAddToBackStack,也会将 Fragment Transaction 添加到 backstack

问题描述

这是一个回购这个错误的示例代码:

如果我连续替换 3 个片段,并禁用第二个片段添加到后台堆栈中。

        fragmentManager = supportFragmentManager
        val fargmentA = FragmentA()
        fragmentManager.beginTransaction().replace(R.id.container, fargmentA).addToBackStack("a").commitAllowingStateLoss();

        val fargmentB = FragmentB()
        fragmentManager.beginTransaction().replace(R.id.container, fargmentB).disallowAddToBackStack().commitAllowingStateLoss();
        
        val fargmentC = FargmentC()
        fragmentManager.beginTransaction().replace(R.id.container, fargmentC).addToBackStack("c").commitAllowingStateLoss();

在上述事务之后,我调用了 popBackStack():

  val count = fragmentManager.backStackEntryCount;
        for(i in 0 until count ){
            fragmentManager.popBackStackImmediate()
        }

我仍然可以看到从 FragmentB 调用 onCreateView() 方法,我不允许将其添加到后台堆栈。

这是一个已知的错误还是片段管理器的行为方式?

谢谢!

标签: androidandroid-fragmentsfragmentmanager

解决方案


有两个主要的事情要记住:

  1. replace()相当于调用remove()当前添加到该容器的每个片段,然后add()使用您的新片段调用,因此该事务fragmentCfragmentB作为其操作的一部分删除
  2. popBackStack()使您完全处于交易前的状态。这意味着fragmentC被删除(与 相反add())和 fragmentB 被添加(与 相反remove()

这意味着预计弹出您的fragmentC交易将fragmentB带回 - 您disallowAddToBackStack()只是意味着您的fragmentB交易永远不会被撤销。

当涉及到同一容器上的混合事务addToBackStack()和非分addToBackStack()片事务时,这实际上会产生一些严重的影响:在您执行fragmentB事务之后,就无法返回到fragmentA.

通常,这意味着如果您确实想要这样做,您可以将非回栈fragmentB事务替换为

fragmentManager.popBackStack()
val fargmentB = FragmentB()
fragmentManager.beginTransaction().replace(R.id.container, fargmentB).addToBackStack("b").commitAllowingStateLoss();

这将确保所有交易addToBackStack()的使用和逆转在每一步都按预期工作。

请注意,您的每一笔交易都应setReorderingAllowed(true)按照片段交易指南使用。这将防止片段向上移动到更高的生命周期级别然后立即向下移动的情况,并确保像 apopBackStack()commit()一起这样的组合操作作为单个原子转换运行。


推荐阅读