儲存及管理導覽狀態
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
以下各節將說明儲存返回堆疊的策略,以及儲存與返回堆疊項目相關聯的狀態。
儲存返回堆疊
為提供良好的使用者體驗,請務必確保應用程式的導覽狀態在各種生命週期事件 (包括設定變更和程序終止) 中持續存在。在 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
可在設定變更 (例如螢幕旋轉) 時保留 UI 相關狀態。根據預設,ViewModels
的範圍會設為最近的 ViewModelStoreOwner
,通常是 Activity
或 Fragment
。
不過,您可能會將 ViewModel
的範圍限定為後疊配置中的特定 NavEntry
(即特定畫面或目的地),而非整個 Activity
。這樣可確保 ViewModel
的狀態只會在特定 NavEntry
是返回堆疊的一部分時保留,並在彈出 NavEntry
時清除。
androidx.lifecycle:lifecycle-viewmodel-navigation3
外掛程式庫提供 NavEntryDecorator
,可協助完成這項工作。這個修飾符會為每個 NavEntry
提供 ViewModelStoreOwner
。當您在 NavEntry
的內容中建立 ViewModel
(例如在 Compose 中使用 viewModel()
) 時,系統會自動將其範圍限制為返回堆疊中該特定 NavEntry
的鍵。也就是說,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 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-07-27 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間: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"]]