Android 13下FragmentManager已销毁异常的排查与解决求助
问题
我的应用在Firebase Crashlytics中频繁触发崩溃,崩溃类型为:Fatal Exception: java.lang.IllegalStateException: FragmentManager has been destroyed,统计数据显示97%的崩溃发生在Android 13系统。无法复现该问题,有人推测是所用依赖库版本过时导致,但无法确认,需要该问题的复现方法或解决方案。
崩溃日志:
Fatal Exception: java.lang.IllegalStateException: FragmentManager has been destroyed at androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1641) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1695) at androidx.fragment.app.FragmentManager.executePendingTransactions(FragmentManager.java:564) at com.github.terrakok.cicerone.androidx.AppNavigator.applyCommandsSync(AppNavigator.kt:34) at com.github.terrakok.cicerone.androidx.AppNavigator$applyCommands$1.run(AppNavigator.kt:29) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8741) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
可能的复现方法
- 在Android 13设备上,快速执行多次页面跳转后,立即将应用切到后台,通过系统设置强制停止应用或执行
adb shell am kill com.your.package.name命令回收进程,再重新打开应用,观察是否触发崩溃。 - 模拟生命周期异常:在Activity的
onDestroy()方法执行后,用Handler延迟发送Cicerone导航指令,确保指令在FragmentManager已销毁时执行。 - 组合场景测试:在Android 13设备上,同时进行网络请求回调触发导航、页面快速返回、应用前后台切换的高频组合操作,重复尝试触发问题。
解决方案
1. 更新核心依赖库
- 升级Cicerone库到最新稳定版本,旧版本可能存在Android 13下的FragmentManager生命周期适配问题。
- 同步更新AndroidX Fragment库至
androidx.fragment:fragment-ktx:1.6.x及以上版本,新版本修复了多个FragmentManager在Android 13上的生命周期异常问题。
2. 给导航器添加状态校验
自定义SafeAppNavigator,在执行导航命令前校验Activity和FragmentManager的状态:
class SafeAppNavigator(activity: AppCompatActivity, containerId: Int) : AppNavigator(activity, containerId) { override fun applyCommands(commands: Array<out Command>) { if (activity.isFinishing || activity.isDestroyed || supportFragmentManager.isDestroyed) { return } super.applyCommands(commands) } }
3. 避免在生命周期后期执行导航
- 禁止在Activity的
onDestroy()、Fragment的onDestroyView()及之后的生命周期阶段发起导航操作。 - 异步回调(如网络请求)绑定生命周期,确保仅在组件活跃时执行导航:
viewModel.someLiveData.observe(viewLifecycleOwner) { data -> if (!viewLifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { return@observe } router.navigateTo(SomeScreen) }
4. 处理进程恢复场景
应用从后台回收后重启时,重置导航栈,避免旧指令在异常状态下执行:
class MainActivity : AppCompatActivity() { private lateinit var router: Router override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 初始化Cicerone并处理进程恢复 if (savedInstanceState == null) { router.newRootScreen(HomeScreen) } else { router.replaceScreen(HomeScreen) } } }
内容的提问来源于stack exchange,提问作者Gerald Sapphire
相关产品推荐
相关产品推荐

