android-fragments Android onBackPressed添加片段而不是替换

q5iwbnjs  于 2022-11-14  发布在  Android
关注(0)|答案(1)|浏览(154)

在我的应用中,我有一个TopActionBar片段,它加载在加载MaterialToolbar的MainActivity上,沿着我的导航抽屉。我在这个片段中有一个FrameLayout,我用片段替换它以在页面之间导航。当我替换一个片段(使用我在utils.kt文件中定义的函数),我正在跟踪第一次加载的片段,并将它们添加到BackStack中,这样我就可以弹出它们,并防止该片段的副本被添加到BackStack中。下面是在我的Utils.kt文件中如何管理它的相关逻辑:

fun replaceFragment(destinationFragment : Fragment,
                    currentFragment: String,
                    title : String,
                    initialLaunch: Boolean = false
) {
    val destinationFragmentName = destinationFragment.javaClass.simpleName
    val fragmentTag : Fragment? = fragmentManager.findFragmentByTag(destinationFragmentName)
    if(destinationFragmentName !== currentFragment || initialLaunch) {
        val fragmentTransaction = fragmentManager.beginTransaction()
        // some logic to determine animations depending on the fragment being replaced
        if (fragmentTag == null) {
            fragmentTransaction.replace(R.id.frame_layout, destinationFragment, destinationFragmentName)
            fragmentTransaction.addToBackStack(destinationFragmentName)
        } else { // re-use the old fragment
            fragmentTransaction.replace(R.id.frame_layout, destinationFragment, destinationFragmentName)
        }

        fragmentTransaction.commit()
    }
}

下面是我如何在我的MainActivity中重写onBackPressed函数:

override fun onBackPressed() {
    if (fragmentManager.backStackEntryCount > 0) {
        fragmentManager.popBackStackImmediate()
    } else {
        super.onBackPressed()
    }
}

有几件事不能正常工作。以下面的片段流为例:
A -〉B -〉C -〉B -〉C
当我按下返回键时,我会看到以下流程:
BC -〉AC -〉应用关闭
此处同时显示多个片段。
我希望发生的是:
C -〉B -〉A -〉应用关闭
如果我没有条件地addToBackStack,而只是为我替换的每一个片段addToBackStack,它可以正常工作,但是我不希望在BackStack中有多个副本。我需要在BackStack中保留每个片段的最新示例。所以在我的示例中:
A -〉B -〉C -〉B -〉C
BackStack将不再有第一个C,只有最近的一个。

0vvn1miw

0vvn1miw1#

根据FragmentManager指南:
当您在事务上调用addToBackStack()时,请注意,该事务可以包含任意数量的操作,例如添加多个片段、替换多个容器中的片段等。当弹出回栈时,所有这些操作都将作为单个原子操作被反转。如果您在popBackStack()调用之前提交了其他事务,并且如果您 * 没有 * 使用addToBackStack()进行该事务,则这些操作 * 不会 * 反转。因此,在单个FragmentManager中,避免将影响后栈的事务与不影响后栈的事务交错。
因此,您所体验到的是您对addToBackStack所做的操作被反转(导致B的原始副本重新出现),同时没有接触到新的C(您没有使用addToBackStack)。
FragmentManager的后栈就是这样的:这意味着你不能从栈中移除B,除非它在backstack的顶部。这意味着没有办法从栈的中间移除B,除非使用支持多个backstack这样的东西来完全交换独立的backstack。
如果你只是想确保在堆栈的顶部只有一个B的副本,那么在无条件地对新示例使用addToBackStack()之前,如果名称相同,你会希望使用popBackStack()删除最上面的副本。

相关问题