Navigation 3 rappresenta un cambiamento fondamentale nel modo in cui Jetpack Compose gestisce lo stato di navigazione e offre vantaggi architettonici significativi rispetto a Navigation 2.
Scopri le modifiche architettoniche e i passaggi necessari per eseguire la migrazione di un'app Wear Compose da Navigation 2 a Navigation 3.
Vantaggi principali di Navigation 3
- Controllo diretto dello stack Back:
NavBackStackè fondamentalmente solo un elenco modificabile di oggettiNavKey, che rappresenta la cronologia delle schermate visitate dall'utente. Puoi controllarlo esattamente come faresti con qualsiasi KotlinMutableList(add,removeLast,clear). Manipola direttamente l'elenco per eseguire azioni di navigazione, ad esempio aggiungendo una chiave per andare avanti o rimuovendo una chiave per tornare indietro. - Design Compose-First: lo stack Back è modellato come stato osservabile standard stato. La modifica della cronologia di navigazione si comporta esattamente come l'aggiornamento di qualsiasi altro stato di Compose, attivando automaticamente la ricomposizione per visualizzare la schermata corrente.
- Type-Safe per impostazione predefinita: le route basate su stringhe vengono eliminate completamente. La navigazione utilizza oggetti dati e classi di dati serializzabili.
- Presentazioni disaccoppiate (strategie di scena): il livello di transizione dell'UI
(
NavDisplayeSwipeDismissableSceneStrategy) è completamente separato dal monitoraggio dello stato (NavBackStack), consentendo una più semplice integrazione delle transizioni di navigazione integrate di Wear OS.
Passi per la migrazione
1. Aggiorna le dipendenze
Rimuovi la vecchia dipendenza androidx.wear.compose:compose-navigation e introduci le nuove dipendenze di Navigation 3 suddivise, insieme al supporto per la serializzazione Kotlin.
Rimuovi:
implementation("androidx.wear.compose:compose-navigation:...")
Aggiungi:
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. Aggiorna le destinazioni per implementare NavKey
In Navigation 2, potresti aver utilizzato stringhe o oggetti generici per il routing. In
Navigation 3, devi implementare l'interfaccia di marcatura NavKey e
annotare ogni oggetto schermata con @Serializable.
Perché è necessario? Affinché lo stack Back possa essere salvato e
ripristinato in caso di interruzione del processo, il navigation3-runtime si basa su
kotlinx-serialization per serializzare lo stato.
Prima (Navigation 2 - Route generiche Type-Safe):
sealed class Nav2Screen { data object Landing : Nav2Screen() data object List : Nav2Screen() }
Dopo (Navigation 3 - NavKey + Serializable):
@Serializable sealed interface MigrationScreen : NavKey { @Serializable data object Landing : MigrationScreen @Serializable data object List : MigrationScreen }
3. Sostituisci la logica di routing (NavController con NavBackStack)
Sostituisci il tuo NavController con un NavBackStack inizializzato utilizzando
rememberNavBackStack. Devi anche creare un'istanza di
SwipeDismissableSceneStrategy specificamente per Wear OS.
Prima (Navigation 2):
val navController = rememberSwipeDismissableNavController()
Dopo (Navigation 3):
val backStack = rememberNavBackStack(MigrationScreen.Landing as NavKey) val strategy = rememberSwipeDismissableSceneStrategy<NavKey>()
4. Sostituisci NavHost con NavDisplay e il DSL entryProvider
Il container NavHost e il relativo builder
DSL composable("route") { ... } interno vengono sostituiti da NavDisplay e dal DSL entryProvider {
entry<Key> { ... } }.
Prima (Navigation 2):
SwipeDismissableNavHost(navController = navController, startDestination = "menu") { composable("menu") { GreetingScreen( onShowList = { navController.navigate("list") } ) } composable("list") { ListScreen() } }
Dopo (Navigation 3):
NavDisplay( backStack = backStack, sceneStrategies = listOf(strategy), entryProvider = entryProvider { entry<MigrationScreen.Landing> { GreetingScreen( onShowList = { backStack.add(MigrationScreen.List) } ) } entry<MigrationScreen.List> { ListScreen() } } )