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