如何在Compose Destination中跨Activity/进程销毁保留导航状态?
解决Compose Destinations跨Activity/进程销毁保存导航状态的问题
你的代码中,Activity销毁恢复后导航回到初始页面,核心原因是没有保存并恢复导航控制器的状态。要实现跨Activity正常销毁重建、甚至进程销毁后的导航状态恢复,需要结合内存状态保存和本地持久化存储两种方式,具体实现如下:
实现步骤与代码示例
class BaseActivity : AppCompatActivity() { // 定义本地存储的键名 private val NAV_STATE_PREFS = "nav_state_prefs" private val NAV_STATE_KEY = "nav_controller_state" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 从本地存储读取之前保存的导航状态(应对进程销毁场景) val savedNavState = getSharedPreferences(NAV_STATE_PREFS, MODE_PRIVATE) .getBundle(NAV_STATE_KEY) setContent { MyTheme { val navController = rememberNavController() // 监听导航状态变化,实时保存到本地存储 DisposableEffect(navController) { val listener = NavController.OnDestinationChangedListener { _, _, _ -> navController.saveState()?.let { state -> getSharedPreferences(NAV_STATE_PREFS, MODE_PRIVATE) .edit() .putBundle(NAV_STATE_KEY, state) .apply() } } navController.addOnDestinationChangedListener(listener) // 组件销毁时移除监听 onDispose { navController.removeOnDestinationChangedListener(listener) } } // 恢复导航状态:优先用本地存储的状态,其次用Activity的savedInstanceState val restoreState = savedNavState ?: savedInstanceState?.getBundle(NAV_STATE_KEY) restoreState?.let { navController.restoreState(it) } DestinationsNavHost( navGraph = NavGraphs.root, navController = navController, // 若已恢复状态,则无需指定startRoute,避免覆盖导航栈;否则用默认初始页 startRoute = restoreState?.run { null } ?: FirstScreenDestination ) } } } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) // 保存状态到Activity的savedInstanceState(应对屏幕旋转等正常销毁重建场景) navController.saveState()?.let { outState.putBundle(NAV_STATE_KEY, it) } } override fun onDestroy() { super.onDestroy() // 可选:用户主动退出APP时清除本地状态,下次启动回到初始页 if (isFinishing) { getSharedPreferences(NAV_STATE_PREFS, MODE_PRIVATE) .edit() .remove(NAV_STATE_KEY) .apply() } } }
关键说明
- 实时持久化:通过
DisposableEffect监听导航变化,每次页面跳转都将当前导航栈状态保存到SharedPreferences,确保进程被系统回收后仍能读取到状态。 - 状态恢复优先级:启动时优先读取本地存储的状态(应对进程销毁),其次读取Activity的
savedInstanceState(应对正常销毁重建),恢复到导航控制器中。 - 避免初始页覆盖:恢复状态后将
startRoute设为null,防止默认初始页覆盖已恢复的导航栈。 - 主动退出清除状态:在
onDestroy中判断用户是否主动退出APP,若是则清除本地状态,保证下次启动从初始页开始。
内容的提问来源于stack exchange,提问作者Bencri
相关产品推荐
相关产品推荐

