我试图用Activity中的Fragments来处理状态和导航问题,但是在尝试正确保留导航状态时感到困惑。说我有这种导航路径:
Activity
|
FragA
|_____________
| | |
FragB FragC FragD
|
FragE
FragA是创建“活动”时显示的初始片段。您可以从FragA导航到FragB / FragC / FragD。您可以从FragC导航到FragE。在每个级别上,片段都会添加到后台,因此路径可能是例如FragA> FragD或FragA> FragC> FragE。
我正在使用此代码设置第一个片段:
private fun setFragment(fragment: Fragment) {
fragmentManager
.beginTransaction()
.replace(R.id.container, fragment)
.commit()
}
此代码设置下一个片段:
fun pushFragment(fragment: Fragment)
fragmentManager
.beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack(null)
.commit()
}
为了处理活动何时重新开始,我使用onSaveInstanceState
和onRestoreInstanceState
保存片段的当前位置。
在我的onCreate
中,我基本上是这样做的:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity)
if (savedInstanceState == null) {
displayFragment(FragA)
}
}
private fun displayFragment(page: String) {
currentFragment = page
when (page) {
FRAG_A -> setFragment(FragA())
FRAG_B -> pushFragment(FragB())
FRAG_C -> pushFragment(FragC())
FRAG_D -> pushFragment(FragD())
FRAG_E -> pushFragment(FragE())
}
}
例如,当我当前在FragC上时,一切正常。我重新启动了活动,并在重新创建活动后按预期返回了FragC,但是一旦尝试导航至FragE,我就会被IllegalStateException
击中。
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
因此,在重新创建活动之后,如果我尝试对某个片段事务进行commit()
,则该异常会崩溃。为什么?我的理解是,在活动重新启动之前调用onSaveInstanceState
时状态已经保存,为什么在重新创建活动后提交事务是非法的?
我已经读到某些解决方案使用commitAllowingStateLoss()
代替commit()
,但是我不太了解使用它代替其他方法的效果。
当我使用commitAllowingStateLoss()
并打印日志时,我得到了:
E/Debug: OnCreate Activity
E/Debug: Set fragment: FragA
E/Debug: Push fragment: FragC
<Restarting the activity>
E/Debug: onSaveInstanceState called
E/Debug: OnCreate Activity
E/Debug: onRestoreInstanceState called
<Navigating to FragE>
E/Debug: Push fragment: Frag E
E/Debug: Push fragment: Frag E
那里发生了什么?日志显示好像我的用于设置FragE的片段事务被调用了两次,但是当我在应用程序上来回导航时,backstack似乎没有任何问题,但是每次我推送一个新片段时,日志都会打印两次。
这是处理片段导航的正确方法吗?