SupportFragmentManager 销毁,在幕后

SupportFragmentManager destroyed, behind the scenes

我的 MainActivity:

上有这个场景
 // onCreate
firebaseAuth.addAuthStateListener { firebaseAuth ->
            when (firebaseAuth.currentUser) {
                null -> {
                    hideAppBars()
                    clearBackStack(supportFragmentManager)
                    showFragment(fragment = LoginOrRegisterFragment())
                }
                else -> {
                    showAppBars()
                    clearBackStack(supportFragmentManager)
                    showFragment(fragment = HomeFragment())
                }
            }
        }

clearBastack 只是一种弹出 Fragments 完整后台堆栈的方法:

private fun clearBackStack(fragmentManager: FragmentManager) {
        with(fragmentManager) {
            if (backStackEntryCount > 0)
                popBackStack()
        }
    }

showFragment方法:

fun showFragment(fragment: Fragment, addToBackStack: Boolean = false) {
            supportFragmentManager.beginTransaction().apply {
                replace(R.id.fragmentContainer, fragment)
                if (addToBackStack) addToBackStack(null)
            }.commit()
    }

在通常的流程中,一切正常。点击登录:BackStack 清除,然后从 LoginFragment 我到达 HomeFragment。但是,如果我在 LoginFragment 和 resume 时按回键,我会得到 IllegalStateException: FragmentManager has been destroyed

问题似乎可以解决

明确检查 if(!supportFragmentManager.isDestroyed):

fun showFragment(fragment: Fragment, addToBackStack: Boolean = false) {
        if (!supportFragmentManager.isDestroyed) {
            supportFragmentManager.beginTransaction().apply {
                replace(R.id.fragmentContainer, fragment)
                if (addToBackStack) addToBackStack(null)
            }.commit()
        }
    }

更新:完整堆栈跟踪:

java.lang.IllegalStateException: FragmentManager has been destroyed
        at androidx.fragment.app.FragmentManager.enqueueAction(FragmentManager.java:1725)
        at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:321)
        at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:286)
        at com.coroutinedispatcher.datacrypt.MainActivity.showFragment(MainActivity.kt:57)
        at com.coroutinedispatcher.datacrypt.MainActivity.showFragment$default(MainActivity.kt:52)
        at com.coroutinedispatcher.datacrypt.MainActivity$onCreate.onAuthStateChanged(MainActivity.kt:36)
        at com.google.firebase.auth.zzj.run(com.google.firebase:firebase-auth@@19.4.0:3)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at com.google.android.gms.internal.firebase_auth.zzj.dispatchMessage(com.google.firebase:firebase-auth@@19.4.0:6)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

抛出的行是supportFragmentManager.apply{bla()}.commit()

问题是,为什么,后台实际发生了什么?

您应该删除 Activity 的 onDestroy 中的 AuthStateListnener。

 // onCreate
private val authStateListener = AuthStateListener { firebaseAuth ->
            when (firebaseAuth.currentUser) {
                null -> {
                    hideAppBars()
                    clearBackStack(supportFragmentManager)
                    showFragment(fragment = LoginOrRegisterFragment())
                }
                else -> {
                    showAppBars()
                    clearBackStack(supportFragmentManager)
                    showFragment(fragment = HomeFragment())
                }
            }
        }

override fun onCreate(...) {
    super.onCreate(...)
    firebaseAuth.addAuthStateListener(authStateListener)
}


override fun onDestroy() {
    firebaseAuth.removeAuthStateListener(authStateListener)
    super.onDestroy()
}

尽管从技术上讲,您还应该考虑到这仍然会在 onStop 之后触发片段事务,这会导致 this action cannot be performed after onSaveInstanceState 错误,因此您实际上应该只在 [=20] 时处理导航操作=] 至少开始了。

您可以使用 https://github.com/Zhuinden/live-event 作为例子。