Navigation 3 stellt eine grundlegende Änderung in der Art und Weise dar, wie der Navigationsstatus in Jetpack Compose verarbeitet wird, und bietet erhebliche architektonische Vorteile gegenüber Navigation 2.
Hier erfahren Sie mehr über die architektonischen Änderungen und die Schritte, die für die Migration einer Wear Compose-App von Navigation 2 zu Navigation 3 erforderlich sind.
Wichtigste Vorteile von Navigation 3
- Direkte Backstack-Steuerung: Der
NavBackStackist im Grunde nur eine veränderliche Liste vonNavKey-Objekten, die den Verlauf der Bildschirme darstellen, die der Nutzer besucht hat. Sie steuern sie genau wie jede andere Kotlin-MutableList(add,removeLast,clear). Sie bearbeiten die Liste direkt, um Navigationsaktionen auszuführen, z. B. einen Schlüssel hinzuzufügen, um vorwärts zu gehen, oder einen Schlüssel zu entfernen, um zurückzugehen. - Compose-First-Design: Der Backstack wird als standardmäßiger beobachtbarer Status modelliert. Wenn Sie Ihren Navigationsverlauf ändern, wird das genauso behandelt wie bei der Aktualisierung eines anderen Compose-Zustands. Es wird automatisch eine Neukomposition ausgelöst, um den aktuellen Bildschirm anzuzeigen.
- Standardmäßig typsicher: Stringbasierte Routen werden vollständig entfernt. Für die Navigation werden serialisierbare Datenobjekte und Datenklassen verwendet.
- Entkoppelte Präsentationen (Szenenstrategien): Die UI-Übergangsebene (
NavDisplayundSwipeDismissableSceneStrategy) ist vollständig von der Statusverfolgung (NavBackStack) getrennt. Dadurch lassen sich integrierte Wear OS-Navigationsübergänge einfacher einbinden.
Migrationsschritte
1. Abhängigkeiten aktualisieren
Entfernen Sie die alte androidx.wear.compose:compose-navigation-Abhängigkeit und fügen Sie die neuen geteilten Navigation 3-Abhängigkeiten sowie die Unterstützung für die Kotlin-Serialisierung hinzu.
Entfernen:
implementation("androidx.wear.compose:compose-navigation:...")
Hinzufügen:
implementation("androidx.navigation3:navigation3-runtime:...") // State logic
implementation("androidx.navigation3:navigation3-ui:...") // Display logic
implementation("androidx.wear.compose:compose-navigation3:...") // Wear gestures
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:...") // Requires compiler plugin
2. Ziele aktualisieren, um NavKey zu implementieren
In Navigation 2 haben Sie möglicherweise Strings oder generische Objekte für das Routing verwendet. In Navigation 3 müssen Sie die Markierungsschnittstelle NavKey implementieren und jedes Bildschirmobjekt mit @Serializable annotieren.
Warum ist das erforderlich? Damit der Backstack bei einem Prozessabsturz gespeichert und wiederhergestellt werden kann, verwendet die zugrunde liegende navigation3-runtime kotlinx-serialization, um den Status zu serialisieren.
Vorher (Navigation 2 – Typsichere generische Routen):
sealed class Nav2Screen { data object Landing : Nav2Screen() data object List : Nav2Screen() }
Nachher (Navigation 3 – NavKey + Serializable):
@Serializable sealed interface MigrationScreen : NavKey { @Serializable data object Landing : MigrationScreen @Serializable data object List : MigrationScreen }
3. Ersetzen Sie die Routing-Logik (NavController bis NavBackStack).
Ersetzen Sie NavController durch ein NavBackStack, das über rememberNavBackStack initialisiert wurde. Außerdem müssen Sie SwipeDismissableSceneStrategy speziell für Wear OS instanziieren.
Vorher (Navigation 2):
val navController = rememberSwipeDismissableNavController()
Nachher (Navigation 3):
val backStack = rememberNavBackStack(MigrationScreen.Landing as NavKey) val strategy = rememberSwipeDismissableSceneStrategy<NavKey>()
4. Ersetzen Sie NavHost durch NavDisplay und die entryProvider-DSL.
Der NavHost-Container und die zugehörige interne composable("route") { ... }-Builder-DSL werden durch NavDisplay und die entryProvider-{
entry<Key> { ... } }-DSL ersetzt.
Vorher (Navigation 2):
SwipeDismissableNavHost(navController = navController, startDestination = "menu") { composable("menu") { GreetingScreen( onShowList = { navController.navigate("list") } ) } composable("list") { ListScreen() } }
Nachher (Navigation 3):
NavDisplay( backStack = backStack, sceneStrategies = listOf(strategy), entryProvider = entryProvider { entry<MigrationScreen.Landing> { GreetingScreen( onShowList = { backStack.add(MigrationScreen.List) } ) } entry<MigrationScreen.List> { ListScreen() } } )