以下部分介绍了保存返回堆栈和存储与返回堆栈中的条目关联的状态的策略。
保存返回堆栈
确保应用的导航状态在各种生命周期事件(包括配置更改和进程终止)中保持不变,对于提供良好的用户体验至关重要。在 Navigation 3 中,您拥有自己的返回堆栈,因此没有严格的准则来规定如何创建或保存它。不过,Navigation 3 确实提供了一种便捷方法,可为您提供可保存的返回堆栈:rememberNavBackStack
。
使用 rememberNavBackStack
rememberNavBackStack
可组合函数旨在创建一个在配置更改和进程终止后保留下来的返回堆栈。
为了让 rememberNavBackStack
正常运行,返回堆栈中的每个键都必须遵循特定要求:
- 实现
NavKey
接口:返回堆栈中的每个键都必须实现NavKey
接口。这可用作标记接口,用于向库发出可以保存键的信号。 - 添加
@Serializable
注解:除了实现NavKey
之外,您的键类和对象还必须带有@Serializable
注解。
以下代码段展示了 rememberNavBackStack
的正确实现:
@Serializable data object Home : NavKey @Composable fun NavBackStack() { val backStack = rememberNavBackStack(Home) }
替代方案:存储在 ViewModel
中
管理返回堆栈的另一种方法是将其存储在 ViewModel
中。如需在使用 ViewModel
或任何其他自定义存储空间时在进程终止后保持持久性,您需要执行以下操作:
- 确保您的按键可序列化:与
rememberNavBackStack
一样,您的导航按键必须可序列化。 - 手动处理序列化和反序列化:您负责手动将每个键的序列化表示法保存到永久存储空间(例如
SharedPreferences
、数据库或文件)时,应用会进入后台或恢复。
将 ViewModel
的范围限定为 NavEntry
ViewModels
用于在发生屏幕旋转等配置更改时保留界面相关状态。默认情况下,ViewModels
的范围限定为最近的 ViewModelStoreOwner
,通常是 Activity
或 Fragment
。
不过,您可能希望将 ViewModel
的范围限定为返回堆栈上的特定 NavEntry
(即特定屏幕或目的地),而不是整个 Activity
。这样可确保仅在特定 NavEntry
位于返回堆栈中时保留 ViewModel
的状态,并在 NavEntry
被弹出时清除该状态。
androidx.lifecycle:lifecycle-viewmodel-navigation3
插件库提供了一个 NavEntryDecorator
来帮助实现这一点。此装饰器会为每个 NavEntry
提供一个 ViewModelStoreOwner
。当您在 NavEntry
的内容中创建 ViewModel
(例如,在 Compose 中使用 viewModel()
)时,系统会自动将其作用域限定为返回堆栈上该特定 NavEntry
的键。这意味着,当 NavEntry
添加到返回堆栈时,系统会创建 ViewModel
,并在移除 NavEntry
时清除 ViewModel
。
如需使用 NavEntryDecorator
将 ViewModel
限定为 NavEntry
,请按以下步骤操作:
- 将
androidx.lifecycle:lifecycle-viewmodel-navigation3
依赖项添加到app/build.gradle.kts
文件中。 - 在构建
NavDisplay
时,将rememberSavedStateNavEntryDecorator()
添加到entryDecorators
列表。 - 将其他装饰器添加到
NavDisplay
中。
NavDisplay( entryDecorators = listOf( // Add the default decorators for managing scenes and saving state rememberSceneSetupNavEntryDecorator(), rememberSavedStateNavEntryDecorator(), // Then add the view model store decorator rememberViewModelStoreNavEntryDecorator() ), backStack = backStack, entryProvider = entryProvider { }, )