// Define keys that will identify contentdataobjectProductListdataclassProductDetail(valid:String)@ComposablefunMyApp(){// Create a back stack, specifying the key the app should start withvalbackStack=remember{mutableStateListOf<Any>(ProductList)}// Supply your back stack to a NavDisplay so it can reflect changes in the UI// ...more on this below...// Push a key onto the back stack (navigate forward), the navigation library will reflect the change in statebackStack.add(ProductDetail(id="ABC"))// Pop a key off the back stack (navigate back), the navigation library will reflect the change in statebackStack.removeLastOrNull()}
返回堆栈 - 此项应为 SnapshotStateList<T> 类型,其中 T 是返回堆栈键的类型。它是一个可观察的 List,因此当它发生变化时,会触发 NavDisplay 的重组。
用于将返回堆栈中的键转换为 NavEntry 的 entryProvider。
(可选)向 onBack 参数提供 lambda。当用户触发返回事件时,系统会调用此方法。
以下示例展示了如何创建 NavDisplay。
dataobjectHomedataclassProduct(valid:String)@ComposablefunNavExample(){valbackStack=remember{mutableStateListOf<Any>(Home)}NavDisplay(backStack=backStack,onBack={backStack.removeLastOrNull()},entryProvider={key->
when(key){isHome->NavEntry(key){ContentGreen("Welcome to Nav3"){Button(onClick={backStack.add(Product("123"))}){Text("Click to navigate")}}}isProduct->NavEntry(key){ContentBlue("Product ${key.id} ")}else->NavEntry(Unit){Text("Unknown route")}}})}
[null,null,["最后更新时间 (UTC):2025-07-27。"],[],[],null,["# Understand and implement the basics\n\nNavigation describes the way users move around your app. Users interact with UI\nelements, usually by tapping or clicking on them, and the app responds by\ndisplaying new content. If the user wants to go back to the previous content,\nthey use the back gesture or tap the back button.\n\nModeling navigation state\n-------------------------\n\nA convenient way of modeling this behavior is with a stack of content. As the\nuser navigates *forward* to new content, it is pushed on top of the stack. When\nthey go *back* from that content, it is popped off the stack and the previous\ncontent is displayed. In navigation terms, this stack is usually referred to as\nthe **back stack** because it represents the content that the user *can go back\nto*.\n**Figure 1.** Diagram showing how the back stack changes with user navigation events.\n\nCreate a back stack\n-------------------\n\nIn Navigation 3, the back stack does not actually contain content. Instead, it\ncontains *references to content* , known as **keys**. Keys can be any type but\nare usually simple, serializable data classes. Using references rather than\ncontent has the following benefits:\n\n- It is simple to navigate by pushing keys onto the back stack.\n- As long as the keys are serializable, the back stack can be saved to persistent storage, allowing it to survive configuration changes and process death. This is important because users expect to leave your app, come back to it later, and pick up where they left off with the same content being displayed. See [Save your back stack](/guide/navigation/navigation-3/save-state#save-back) for more information.\n\nA key concept in the Navigation 3 API is that you own the back stack. The\nlibrary:\n\n- Expects that your back stack will be a snapshot-state backed `List\u003cT\u003e`, where `T` is the type of your back stack `keys`. You can use `Any` or you can provide your own, more strongly-typed keys. When you see the terms \"push\" or \"pop\", the underlying implementation is to add or remove items from the end of a list.\n- Observes your back stack and reflects its state in the UI using a [`NavDisplay`](/reference/kotlin/androidx/navigation3/ui/package-summary#NavDisplay(kotlin.collections.List,androidx.compose.ui.Modifier,androidx.compose.ui.Alignment,kotlin.Function1,kotlin.collections.List,androidx.navigation3.ui.SceneStrategy,androidx.compose.animation.SizeTransform,kotlin.Function1,kotlin.Function1,kotlin.Function1,kotlin.Function1)).\n\nThe following example shows how to create keys and a back stack, and modify the\nback stack in response to user navigation events:\n\n\n```kotlin\n// Define keys that will identify content\ndata object ProductList\ndata class ProductDetail(val id: String)\n\n@Composable\nfun MyApp() {\n\n // Create a back stack, specifying the key the app should start with\n val backStack = remember { mutableStateListOf\u003cAny\u003e(ProductList) }\n\n // Supply your back stack to a NavDisplay so it can reflect changes in the UI\n // ...more on this below...\n\n // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state\n backStack.add(ProductDetail(id = \"ABC\"))\n\n // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state\n backStack.removeLastOrNull()\n}https://github.com/android/snippets/blob/26d364466ee1c03d658ba2f0905f7cc1a97afefa/compose/snippets/src/main/java/com/example/compose/snippets/navigation3/basic/BasicSnippets.kt#L33-L51\n```\n\n\u003cbr /\u003e\n\nResolve keys to content\n-----------------------\n\nContent is modeled in Navigation 3 using [`NavEntry`](/reference/kotlin/androidx/navigation3/runtime/NavEntry), which is a class\ncontaining a composable function. It represents a *destination* - a single piece\nof content that the user can navigate *forward to* and *back from*.\n\nA `NavEntry` can also contain metadata - information about the content. This\nmetadata can be read by container objects, like `NavDisplay`, to help them\ndecide how to display the `NavEntry`'s content. For example, metadata can be\nused to override the default animations for a specific `NavEntry`. NavEntry\n`metadata` is a map of `String` keys to `Any` values, providing versatile data\nstorage.\n\nTo convert a `key` to a `NavEntry`, create an Entry Provider. This is a\nfunction that accepts a `key` and returns a `NavEntry` for that `key`. It is\nusually defined as a lambda parameter when creating a `NavDisplay`.\n\nThere are two ways to create an Entry Provider, either by creating a lambda\nfunction directly, or by using the [`entryProvider`](/reference/kotlin/androidx/navigation3/runtime/package-summary#entryProvider(kotlin.Function1,kotlin.Function1)) DSL.\n\n### Create an Entry Provider function directly\n\nYou typically create an Entry Provider function using a `when` statement, with\na branch for each of your keys.\n\n\n```kotlin\nentryProvider = { key -\u003e\n when (key) {\n is ProductList -\u003e NavEntry(key) { Text(\"Product List\") }\n is ProductDetail -\u003e NavEntry(\n key,\n metadata = mapOf(\"extraDataKey\" to \"extraDataValue\")\n ) { Text(\"Product ${key.id} \") }\n\n else -\u003e {\n NavEntry(Unit) { Text(text = \"Invalid Key: $it\") }\n }\n }\n}https://github.com/android/snippets/blob/26d364466ee1c03d658ba2f0905f7cc1a97afefa/compose/snippets/src/main/java/com/example/compose/snippets/navigation3/basic/BasicSnippets.kt#L60-L72\n```\n\n\u003cbr /\u003e\n\n### Use the `entryProvider` DSL\n\nThe `entryProvider` DSL can simplify your lambda function by avoiding the need\nto test against each of your key types, and construct a `NavEntry` for each one.\nUse the `entryProvider` builder function for this. It also includes default\nfallback behavior (throwing an error) if the key isn't found.\n\n\n```kotlin\nentryProvider = entryProvider {\n entry\u003cProductList\u003e { Text(\"Product List\") }\n entry\u003cProductDetail\u003e(\n metadata = mapOf(\"extraDataKey\" to \"extraDataValue\")\n ) { key -\u003e Text(\"Product ${key.id} \") }\n}https://github.com/android/snippets/blob/26d364466ee1c03d658ba2f0905f7cc1a97afefa/compose/snippets/src/main/java/com/example/compose/snippets/navigation3/basic/BasicSnippets.kt#L83-L88\n```\n\n\u003cbr /\u003e\n\nNote the following from the snippet:\n\n- `entry` is used to define a `NavEntry` with the given type and composable content\n- `entry` accepts a `metadata` parameter to set `NavEntry.metadata`\n\nDisplay the back stack\n----------------------\n\nThe back stack represents your app's navigation state. Whenever the back stack\nchanges, the app UI should reflect the new back stack state. In Navigation 3, a\n`NavDisplay` observes your back stack and updates its UI accordingly. Construct\nit with following parameters:\n\n- Your back stack - this should be of type `SnapshotStateList\u003cT\u003e`, where `T` is the type of your back stack keys. It is an observable `List` so that it triggers recomposition of `NavDisplay` when it changes.\n- An `entryProvider` to convert the keys in your back stack to `NavEntry`s.\n- Optionally, supply a lambda to the `onBack` parameter. This is called when the user triggers a back event.\n\nThe following example shows how to create a `NavDisplay`.\n\n\n```kotlin\ndata object Home\ndata class Product(val id: String)\n\n@Composable\nfun NavExample() {\n\n val backStack = remember { mutableStateListOf\u003cAny\u003e(Home) }\n\n NavDisplay(\n backStack = backStack,\n onBack = { backStack.removeLastOrNull() },\n entryProvider = { key -\u003e\n when (key) {\n is Home -\u003e NavEntry(key) {\n ContentGreen(\"Welcome to Nav3\") {\n Button(onClick = {\n backStack.add(Product(\"123\"))\n }) {\n Text(\"Click to navigate\")\n }\n }\n }\n\n is Product -\u003e NavEntry(key) {\n ContentBlue(\"Product ${key.id} \")\n }\n\n else -\u003e NavEntry(Unit) { Text(\"Unknown route\") }\n }\n }\n )\n}https://github.com/android/snippets/blob/26d364466ee1c03d658ba2f0905f7cc1a97afefa/compose/snippets/src/main/java/com/example/compose/snippets/navigation3/basic/BasicSnippets.kt#L94-L125\n```\n\n\u003cbr /\u003e\n\nBy default, the `NavDisplay` shows the topmost `NavEntry` on the back stack in a\nsingle pane layout. The following recording shows this app running:\n**Figure 2.** `NavDisplay` default behavior with two destinations.\n\nPutting it all together\n-----------------------\n\nThe following diagram shows how data flows between the various objects in\nNavigation 3:\n**Figure 3.** Diagram showing how data flows through various objects in Navigation 3.\n\n1. **Navigation events initiate changes**. Keys are added or removed from the\n back stack in response to user interactions.\n\n2. **Change in back stack state triggers content retrieval** . The `NavDisplay`\n (a composable that renders a back stack) observes the back stack. In its\n default configuration, it displays the topmost back stack entry in a single\n pane layout. When the top key on the back stack changes, the `NavDisplay` uses\n this key to request the corresponding content from the entry provider.\n\n3. **Entry provider supplies content** . The entry provider is a function that\n resolves a key to a `NavEntry`. Upon receiving a key from the `NavDisplay`,\n the entry provider provides the associated `NavEntry`, which contains both the\n key and the content.\n\n4. **Content is displayed** . The `NavDisplay` receives the `NavEntry` and\n displays the content."]]