Navigation 3 rappresenta un cambiamento fondamentale nel modo in cui Jetpack Compose gestisce lo stato di navigazione e offre vantaggi architetturali significativi rispetto a Navigation 2.
Comprendi le modifiche all'architettura e i passaggi necessari per eseguire la migrazione di un'app Wear Compose da Navigation 2 a Navigation 3.
Vantaggi principali di Navigazione 3
- Controllo diretto dello stack indietro:
NavBackStackè fondamentalmente solo un elenco modificabile di oggettiNavKey, che rappresentano la cronologia delle schermate visitate dall'utente. Lo controlli esattamente come faresti con qualsiasiMutableListKotlin (add,removeLast,clear). Manipoli direttamente l'elenco per eseguire azioni di navigazione, ad esempio aggiungendo un tasto per andare avanti o rimuovendo un tasto per tornare indietro. - Compose-First Design: il back stack è modellato come stato osservabile standard. La modifica della cronologia di navigazione si comporta esattamente come l'aggiornamento di qualsiasi altro stato di Compose, attivando automaticamente la ricomposizione per visualizzare lo schermo corrente.
- Type-Safe by Default: 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'interfaccia utente
(
NavDisplayeSwipeDismissableSceneStrategy) è completamente separato dal monitoraggio dello stato (NavBackStack), consentendo un'integrazione più semplice 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 della 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 Navigazione 2, potresti aver utilizzato stringhe o oggetti generici per il routing. In
Navigation 3, devi implementare l'interfaccia marker NavKey e
annotare ogni oggetto dello schermo con @Serializable.
Perché è necessario? Per garantire che lo stack precedente possa essere salvato e
ripristinato in caso di interruzione del processo, navigation3-runtime sottostante si basa su
kotlinx-serialization per serializzare lo stato.
Prima (Navigation 2 - Generic Type-Safe Routes):
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 (da NavController a NavBackStack)
Sostituisci NavController con un NavBackStack inizializzato tramite
rememberNavBackStack. Devi anche creare un'istanza di
SwipeDismissableSceneStrategy specificamente per Wear OS.
Prima (navigazione 2):
val navController = rememberSwipeDismissableNavController()
Dopo (navigazione 3):
val backStack = rememberNavBackStack(MigrationScreen.Landing as NavKey) val strategy = rememberSwipeDismissableSceneStrategy<NavKey>()
4. Sostituisci NavHost con NavDisplay e il DSL entryProvider
Il contenitore NavHost e il relativo DSL del builder composable("route") { ... } interno
vengono sostituiti da NavDisplay e dal DSL entryProvider {
entry<Key> { ... } }.
Prima (navigazione 2):
SwipeDismissableNavHost(navController = navController, startDestination = "menu") { composable("menu") { GreetingScreen( onShowList = { navController.navigate("list") } ) } composable("list") { ListScreen() } }
Dopo (navigazione 3):
NavDisplay( backStack = backStack, sceneStrategies = listOf(strategy), entryProvider = entryProvider { entry<MigrationScreen.Landing> { GreetingScreen( onShowList = { backStack.add(MigrationScreen.List) } ) } entry<MigrationScreen.List> { ListScreen() } } )