以下部分介绍了用于保存返回堆栈和存储与返回堆栈上的条目关联的状态的策略。
保存返回堆栈
确保应用在各种生命周期事件(包括配置更改和进程终止)中保持导航状态,对于提供良好的用户体验至关重要。在 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时,将rememberSaveableStateHolderNavEntryDecorator()添加到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 { }, )