保存和管理导航状态
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
以下部分介绍了保存返回堆栈和存储与返回堆栈中的条目关联的状态的策略。
保存返回堆栈
确保应用的导航状态在各种生命周期事件(包括配置更改和进程终止)中保持不变,对于提供良好的用户体验至关重要。在 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 { },
)
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-07-27。
[null,null,["最后更新时间 (UTC):2025-07-27。"],[],[],null,["# Save and manage navigation state\n\nThe following sections describe strategies for saving your back stack and\nstoring state associated with entries on your back stack.\n\nSave your back stack\n--------------------\n\nEnsuring your app's navigation state persists across various lifecycle events,\nincluding configuration changes and process death, is crucial for a good user\nexperience. In Navigation 3, you own your back stack, so there aren't strict\nguidelines on how you should create or save it. However, Navigation 3 does offer\na convenience method that provides you with a saveable back stack:\n[`rememberNavBackStack`](/reference/kotlin/androidx/navigation3/runtime/package-summary#rememberNavBackStack(kotlin.Array)).\n\n### Use `rememberNavBackStack`\n\nThe `rememberNavBackStack` composable function is designed to create a back\nstack that persists across configuration changes and process death.\n\nFor `rememberNavBackStack` to function correctly, each key in your back stack\nmust adhere to specific requirements:\n\n- **Implement `NavKey` interface** : Every key in the back stack must implement the [`NavKey`](/reference/kotlin/androidx/navigation3/runtime/NavKey) interface. This acts as a marker interface that signals to the library that the key can be saved.\n- **Have the `@Serializable` annotation** : In addition to implementing `NavKey`, your key classes and objects must be marked with the `@Serializable` annotation.\n\nThe following snippet shows a correct implementation of `rememberNavBackStack`:\n\n\n```kotlin\n@Serializable\ndata object Home : NavKey\n\n@Composable\nfun NavBackStack() {\n val backStack = rememberNavBackStack(Home)\n}https://github.com/android/snippets/blob/26d364466ee1c03d658ba2f0905f7cc1a97afefa/compose/snippets/src/main/java/com/example/compose/snippets/navigation3/savingstate/SavingStateSnippets.kt#L30-L36\n```\n\n\u003cbr /\u003e\n\n### Alternative: Storing in a `ViewModel`\n\nAnother approach to managing your back stack is to store it in a `ViewModel`.\nFor persistence through process death when using a `ViewModel` or any other\ncustom storage, you need to:\n\n- **Ensure your keys are serializable** : Just like with `rememberNavBackStack`, your navigation keys must be serializable.\n- **Handle serialization and deserialization manually** : You're responsible for manually saving the serialized representation of each key to, and deserializing it from, persistent storage (e.g., `SharedPreferences`, a database, or a file) when your app is going into the background or being restored.\n\nScoping `ViewModel`s to `NavEntry`s\n-----------------------------------\n\n`ViewModels` are used to retain UI-related state across configuration changes,\nsuch as screen rotations. By default, `ViewModels` are scoped to the nearest\n`ViewModelStoreOwner`, which is typically your `Activity` or `Fragment`.\n\nHowever, you might want to scope a `ViewModel` to a specific `NavEntry` (i.e., a\nspecific screen or destination) on the back stack, rather than the entire\n`Activity`. This ensures that the `ViewModel`'s state is retained only while\nthat particular `NavEntry` is part of the back stack, and is cleared when the\n`NavEntry` is popped.\n\nThe `androidx.lifecycle:lifecycle-viewmodel-navigation3` add-on library provides\na `NavEntryDecorator` that facilitates this. This decorator provides a\n`ViewModelStoreOwner` for each `NavEntry`. When you create a `ViewModel` inside a\n`NavEntry`'s content (e.g., using `viewModel()` in Compose), it is automatically\nscoped to that specific `NavEntry`'s key on the back stack. This means the\n`ViewModel` is created when the `NavEntry` is added to the back stack, and\ncleared when it's removed.\n\nTo use `NavEntryDecorator` for scoping `ViewModel`s to `NavEntry`s, follow these\nsteps:\n\n1. Add the `androidx.lifecycle:lifecycle-viewmodel-navigation3` dependency to your `app/build.gradle.kts` file.\n2. Add [`rememberSavedStateNavEntryDecorator()`](/reference/kotlin/androidx/navigation3/runtime/package-summary#rememberSavedStateNavEntryDecorator(androidx.compose.runtime.saveable.SaveableStateHolder)) to the list of `entryDecorators` when constructing a `NavDisplay`.\n3. Add other decorators into your `NavDisplay`.\n\n\n```kotlin\nNavDisplay(\n entryDecorators = listOf(\n // Add the default decorators for managing scenes and saving state\n rememberSceneSetupNavEntryDecorator(),\n rememberSavedStateNavEntryDecorator(),\n // Then add the view model store decorator\n rememberViewModelStoreNavEntryDecorator()\n ),\n backStack = backStack,\n entryProvider = entryProvider { },\n)https://github.com/android/snippets/blob/26d364466ee1c03d658ba2f0905f7cc1a97afefa/compose/snippets/src/main/java/com/example/compose/snippets/navigation3/savingstate/SavingStateSnippets.kt#L45-L55\n```\n\n\u003cbr /\u003e"]]