Die Navigation beschreibt, wie sich Nutzer in Ihrer App bewegen. Nutzer interagieren mit UI-Elementen, in der Regel durch Tippen oder Klicken, und die App reagiert, indem sie neue Inhalte anzeigt. Wenn der Nutzer zum vorherigen Inhalt zurückkehren möchte, verwendet er die Touch-Geste „Zurück“ oder tippt auf den Button „Zurück“.
Navigationsstatus modellieren
Eine bequeme Möglichkeit, dieses Verhalten zu modellieren, ist ein Stapel von Inhalten. Wenn der Nutzer vorwärts zu neuen Inhalten navigiert, werden diese oben auf dem Stack abgelegt. Wenn sie von diesem Inhalt zurückkehren, wird er aus dem Stack entfernt und der vorherige Inhalt wird angezeigt. In der Navigation wird dieser Stack normalerweise als Back Stack bezeichnet, da er die Inhalte darstellt, zu denen der Nutzer zurückkehren kann.
Back Stack erstellen
In Navigation 3 enthält der Back Stack keine Inhalte. Stattdessen enthält sie Verweise auf Inhalte, die als Schlüssel bezeichnet werden. Schlüssel können einen beliebigen Typ haben, sind aber in der Regel einfache, serialisierbare Datenklassen. Die Verwendung von Referenzen anstelle von Inhalten bietet folgende Vorteile:
- Die Navigation ist einfach, da Tasten auf den Back Stack verschoben werden.
- Solange die Schlüssel serialisierbar sind, kann der Back Stack im nichtflüchtigen Speicher gespeichert werden, sodass er Konfigurationsänderungen und Prozessbeendigungen übersteht. Das ist wichtig, weil Nutzer erwarten, dass sie Ihre App verlassen, später zurückkehren und dort weitermachen können, wo sie aufgehört haben, wobei dieselben Inhalte angezeigt werden. Weitere Informationen findest du unter Back Stack speichern.
Ein wichtiges Konzept der Navigation 3 API ist, dass Sie den Back Stack selbst verwalten. Die Bibliothek:
- Es wird erwartet, dass der Back Stack ein Snapshot-Status-gestütztes
List<T>ist, wobeiTder Typ des Back Stack-keysist. Sie könnenAnyverwenden oder eigene, stärker typisierte Schlüssel bereitstellen. Wenn Sie die Begriffe „push“ oder „pop“ sehen, bedeutet das, dass Elemente am Ende einer Liste hinzugefügt oder entfernt werden. - Beobachtet den Back Stack und spiegelt seinen Status in der Benutzeroberfläche mithilfe eines
NavDisplaywider.
Im folgenden Beispiel wird gezeigt, wie Sie Schlüssel und einen Back Stack erstellen und den Back Stack als Reaktion auf Navigationsereignisse des Nutzers ändern:
// Define keys that will identify content data object ProductList data class ProductDetail(val id: String) @Composable fun MyApp() { // Create a back stack, specifying the key the app should start with val backStack = 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 state backStack.add(ProductDetail(id = "ABC")) // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state backStack.removeLastOrNull() }
Schlüssel in Inhalte auflösen
In Navigation 3 werden Inhalte mit NavEntry modelliert. Das ist eine Klasse, die eine zusammensetzbare Funktion enthält. Es stellt ein Ziel dar – einen einzelnen Inhalt, zu dem der Nutzer vorwärts und von dem er zurück navigieren kann.
Ein NavEntry kann auch Metadaten enthalten, also Informationen über den Inhalt. Diese Metadaten können von Containerobjekten wie NavDisplay gelesen werden, um zu entscheiden, wie der Inhalt des NavEntry angezeigt werden soll. Metadaten können beispielsweise verwendet werden, um die Standardanimationen für ein bestimmtes NavEntry zu überschreiben. NavEntry metadata ist eine Zuordnung von String-Schlüsseln zu Any-Werten und bietet eine vielseitige Datenspeicherung.
Wenn Sie einen key in einen NavEntry konvertieren möchten, erstellen Sie einen Eintragsprovider. Diese Funktion akzeptiert einen key und gibt einen NavEntry für diesen key zurück. Sie wird normalerweise als Lambda-Parameter beim Erstellen eines NavDisplay definiert.
Es gibt zwei Möglichkeiten, einen Entry Provider zu erstellen: entweder durch direktes Erstellen einer Lambda-Funktion oder mithilfe der entryProvider-DSL.
Eintragsanbieterfunktion direkt erstellen
In der Regel erstellen Sie eine Entry Provider-Funktion mit einer when-Anweisung, die für jeden Schlüssel einen Zweig enthält.
entryProvider = { key -> when (key) { is ProductList -> NavEntry(key) { Text("Product List") } is ProductDetail -> NavEntry( key, metadata = mapOf("extraDataKey" to "extraDataValue") ) { Text("Product ${key.id} ") } else -> { NavEntry(Unit) { Text(text = "Invalid Key: $it") } } } }
entryProvider-DSL verwenden
Mit der entryProvider-DSL können Sie Ihre Lambda-Funktion vereinfachen, da Sie nicht jeden Schlüsseltyp testen und für jeden einen NavEntry erstellen müssen.
Verwenden Sie dazu die Builder-Funktion entryProvider. Außerdem wird ein Standard-Fallback-Verhalten (Ausgabe eines Fehlers) verwendet, wenn der Schlüssel nicht gefunden wird.
entryProvider = entryProvider { entry<ProductList> { Text("Product List") } entry<ProductDetail>( metadata = mapOf("extraDataKey" to "extraDataValue") ) { key -> Text("Product ${key.id} ") } }
Beachten Sie Folgendes im Snippet:
entrywird verwendet, um einNavEntrymit dem angegebenen Typ und dem zusammensetzbaren Inhalt zu definieren.entryakzeptiert einenmetadata-Parameter, umNavEntry.metadatafestzulegen.
Back Stack anzeigen
Der Back Stack stellt den Navigationsstatus Ihrer App dar. Wenn sich der Back Stack ändert, sollte die App-Benutzeroberfläche den neuen Back Stack-Status widerspiegeln. In Navigation 3 beobachtet ein NavDisplay Ihren Back Stack und aktualisiert die Benutzeroberfläche entsprechend. Erstellen Sie sie mit den folgenden Parametern:
- Ihr Back Stack – dieser sollte vom Typ
SnapshotStateList<T>sein, wobeiTder Typ Ihrer Back Stack-Schlüssel ist. Es ist ein beobachtbaresList, sodass bei einer Änderung die Neuzusammensetzung vonNavDisplayausgelöst wird. - Ein
entryProvider, um die Schlüssel im Back Stack inNavEntry-Objekte zu konvertieren. - Optional können Sie einen Lambda-Wert für den Parameter
onBackangeben. Diese wird aufgerufen, wenn der Nutzer ein Zurück-Ereignis auslöst.
Im folgenden Beispiel wird gezeigt, wie Sie eine NavDisplay erstellen.
data object Home data class Product(val id: String) @Composable fun NavExample() { val backStack = remember { mutableStateListOf<Any>(Home) } NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, entryProvider = { key -> when (key) { is Home -> NavEntry(key) { ContentGreen("Welcome to Nav3") { Button(onClick = { backStack.add(Product("123")) }) { Text("Click to navigate") } } } is Product -> NavEntry(key) { ContentBlue("Product ${key.id} ") } else -> NavEntry(Unit) { Text("Unknown route") } } } ) }
Standardmäßig zeigt die NavDisplay die oberste NavEntry im Back Stack in einem Layout mit einem einzelnen Bereich an. Die folgende Aufnahme zeigt die App in Aktion:

NavDisplay-Standardverhalten mit zwei Zielen.Lebenszyklus des Ziels
NavDisplay verwendet benutzerdefinierte LifecycleOwners, um den Lebenszyklusstatus einer NavEntry sowohl auf Scene-Ebene als auch auf Entry-Ebene zu begrenzen.
Weitere Informationen zu Lebenszyklen in Compose finden Sie unter Lebenszyklus in Jetpack Compose.
Lebenszykluseinschränkungen auf Szenenebene
NavDisplay verwaltet den Lebenszyklus der aktiven Scenes. Obergrenzen auf Szenenebene werden so ermittelt:
Für Szenen ohne Overlay:
RESUMED: Nur zulässig, wenn der Szenenübergang abgeschlossen ist und keine aktiven Overlay-Szenen darüber angezeigt werden.STARTED: Begrenzt aufSTARTEDwährend Szenenübergängen, z. B. beim Vor- oder Zurückgehen oder wenn die Szene von einem Overlay verdeckt wird.
Für Overlay-Szenen wie Dialogfelder oder Ansichten am unteren Rand:
RESUMED: Nur für die oberste, derzeit aktive Overlay-Szene zulässig.STARTED: Begrenzt aufSTARTEDfür alle zugrunde liegenden Overlay-Szenen, die von einem neueren Overlay abgedeckt werden.
Lebenszyklusstatus der Einstiegsklasse
Die Bibliothek verwaltet den maximalen Lebenszyklusstatus jedes einzelnen NavEntry basierend auf seinem Vorhandensein im Back Stack:
RESUMED: Wenn der Eintrag im aktuellen Back Stack vorhanden ist, kann sein Lebenszyklus bis zuRESUMEDreichen (vorbehaltlich der Obergrenze auf Szenenebene).CREATED: Wenn sich der Eintrag nicht mehr im Back Stack befindet, z. B. wenn er entfernt wurde, aber während der Animation noch auf dem Bildschirm gerendert wird, begrenzt die Bibliothek den Lebenszyklus strikt aufCREATED. Dieses Limit sorgt dafür, dass Hintergrund- oder Beendigungseinträge keine aktiven Aufgaben mehr ausführen, z. B. das Erfassen von Abläufen oder das Starten von Koroutinen, die an die StatusRESUMEDoderSTARTEDgebunden sind, während sie ihre Beendigungsübergänge abschließen.
Kombination
Der endgültige Lebenszyklusstatus eines NavEntry wird beispielsweise so aufgelöst:
| Szenario | Obergrenze auf Szenenebene | Einstiegskappe | Effektive Obergrenze |
|---|---|---|---|
| Aktiver Eintrag, Bildschirm mit abgeschlossener Aktion (keine Übergänge oder Overlays) | RESUMED |
RESUMED |
RESUMED |
| Aktiver Eintrag, während des Übergangs (Navigation zu oder von) | STARTED |
RESUMED |
STARTED |
| Aktiver Eintrag, der von einem Overlay verdeckt wird (z. B. wenn ein Dialogfeld geöffnet ist) | STARTED |
RESUMED |
STARTED |
| Eintrag wird ausgeblendet | STARTED oder RESUMED |
CREATED |
CREATED |
Zusammenfassung
Das folgende Diagramm zeigt, wie Daten zwischen den verschiedenen Objekten in Navigation 3 fließen:
Navigationsereignisse initiieren Änderungen. Schlüssel werden als Reaktion auf Nutzerinteraktionen zum Back Stack hinzugefügt oder daraus entfernt.
Änderung des Back-Stack-Status löst Abruf von Inhalten aus Die
NavDisplay(eine zusammensetzbare Funktion, die einen Back Stack rendert) beobachtet den Back Stack. In der Standardkonfiguration wird der oberste Back-Stack-Eintrag in einem Layout mit einem einzelnen Bereich angezeigt. Wenn sich der oberste Schlüssel im Back Stack ändert, verwendet derNavDisplaydiesen Schlüssel, um den entsprechenden Inhalt vom Eintragsprovider anzufordern.Eintragsanbieter stellt Inhalte bereit. Der Eintragsprovider ist eine Funktion, die einen Schlüssel in ein
NavEntryauflöst. Wenn der Eintragsprovider einen Schlüssel vomNavDisplayempfängt, stellt er den zugehörigenNavEntrybereit, der sowohl den Schlüssel als auch den Inhalt enthält.Inhalte werden angezeigt. Der
NavDisplayempfängt dieNavEntryund zeigt den Inhalt an.