L'API Navigation Compose ti consente di navigare tra i componibili in un'app Compose, sfruttando al contempo il componente, l'infrastruttura e le funzionalità di Jetpack Navigation.
Questa pagina descrive come eseguire la migrazione da una navigazione Jetpack basata su frammenti a Navigation Compose, nell'ambito della migrazione più ampia della UI basata su View a Jetpack Compose.
Prerequisiti per la migrazione
Puoi eseguire la migrazione a Navigation Compose una volta che sei in grado di sostituire tutti i tuoi frammenti con i composabili della schermata corrispondenti. I componibili della schermata possono contenere un mix di contenuti Compose e View, ma tutte le destinazioni di navigazione devono essere componibili per consentire la migrazione a Navigation Compose. Fino ad allora, devi continuare a utilizzare il componente di navigazione basato su frammenti nel codebase di interoperabilità di View e Compose. Per saperne di più, consulta la documentazione sull'interoperabilità della navigazione.
Passi per la migrazione
Che tu stia seguendo la nostra strategia di migrazione consigliata o adottando un altro approccio, arriverai a un punto in cui tutte le destinazioni di navigazione sono composabili di schermate, con i frammenti che fungono solo da contenitori composabili. In questa fase, puoi eseguire la migrazione a Navigation Compose.
Se la tua app segue già un pattern di progettazione UDF e la nostra guida all'architettura, la migrazione a Jetpack Compose e Navigation Compose non dovrebbe richiedere importanti rifattorizzazioni di altri livelli dell'app, ad eccezione del livello UI.
Per eseguire la migrazione a Navigation Compose, segui questi passaggi:
- Aggiungi la dipendenza Navigation Compose alla tua app.
Crea un componibile
App-levele aggiungilo aActivitycome punto di accesso di Compose, sostituendo la configurazione del layout della visualizzazione:class SampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample) setContent { SampleApp(/* ... */) } } }
Crea tipi per ogni destinazione di navigazione. Utilizza un
data objectper le destinazioni che non richiedono dati edata classoclassper le destinazioni che richiedono dati.@Serializable data object First @Serializable data class Second(val id: String) @Serializable data object Third
Configura
NavControllerin un punto in cui tutti i componibili che devono farvi riferimento possano accedervi (di solito all'interno del componibileApp). Questo approccio segue i principi dell'innalzamento dello stato e ti consente di utilizzareNavControllercome fonte attendibile per la navigazione tra le schermate componibili e la gestione del back stack:@Composable fun SampleApp() { val navController = rememberNavController() // ... }
Crea l'elemento
NavHostdella tua app all'interno del composableAppe passanavController:@Composable fun SampleApp() { val navController = rememberNavController() SampleNavHost(navController = navController) } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { // ... } }
Aggiungi le
composabledestinazioni per creare il grafico di navigazione. Se ogni schermata è stata precedentemente migrata a Compose, questo passaggio consiste solo nell'estrazione di questi composabili delle schermate dai frammenti nelle destinazionicomposable:class FirstFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { setContent { // FirstScreen(...) EXTRACT FROM HERE } } } } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { composable<First> { FirstScreen(/* ... */) // EXTRACT TO HERE } composable<Second> { SecondScreen(/* ... */) } // ... } }
Se hai seguito le indicazioni su come progettare l'interfaccia utente di Compose, in particolare su come passare
ViewModeled eventi di navigazione ai componibili, il passaggio successivo consiste nel modificare il modo in cui fornisciViewModela ogni componibile della schermata. Spesso puoi utilizzare l'inserimento di Hilt e il suo punto di integrazione con Compose e Navigation tramitehiltViewModel:@Composable fun FirstScreen( // viewModel: FirstViewModel = viewModel(), viewModel: FirstViewModel = hiltViewModel(), onButtonClick: () -> Unit = {}, ) { // ... }
Sostituisci tutte le chiamate di navigazione
findNavController()con quelle dinavControllere passale come eventi di navigazione a ogni schermata componibile, anziché passare l'interonavController. Questo approccio segue le best practice per l'esposizione degli eventi dalle funzioni componibili ai chiamanti e mantienenavControllercome Single Source Of Truth.I dati possono essere passati a una destinazione creando un'istanza della classe di route definita per quella destinazione. Può quindi essere ottenuto direttamente dalla voce del back stack nella destinazione o da un
ViewModelutilizzandoSavedStateHandle.toRoute().@Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { composable<First> { FirstScreen( onButtonClick = { // findNavController().navigate(firstScreenToSecondScreenAction) navController.navigate(Second(id = "ABC")) } ) } composable<Second> { backStackEntry -> val secondRoute = backStackEntry.toRoute<Second>() SecondScreen( id = secondRoute.id, onIconClick = { // findNavController().navigate(secondScreenToThirdScreenAction) navController.navigate(Third) } ) } // ... } }
Rimuovi tutti i frammenti, i layout XML pertinenti, la navigazione non necessaria e altre risorse, nonché le dipendenze di navigazione di Fragment e Jetpack obsolete.
Puoi trovare gli stessi passaggi con ulteriori dettagli relativi a Navigation Compose nella documentazione di configurazione.
Casi d'uso comuni
Indipendentemente dal componente di navigazione che utilizzi, si applicano gli stessi principi di navigazione.
I casi d'uso comuni durante la migrazione includono:
- Vai a un composable
- Naviga con gli argomenti
- Deep ink
- Navigazione nidificata
- Integrazione con la barra di navigazione in basso
- Integrazione con un componente di navigazione personalizzato
Per informazioni più dettagliate su questi casi d'uso, consulta Navigazione con Compose.
Recuperare dati complessi durante la navigazione
Ti consigliamo vivamente di non passare oggetti di dati complessi durante la navigazione. Passa invece le informazioni minime necessarie, come un identificatore univoco o un'altra forma di ID, come argomenti durante l'esecuzione delle azioni di navigazione. Devi archiviare gli oggetti complessi come dati in un'unica Single Source Of Truth, ad esempio il livello dati. Per saperne di più, consulta Recupero di dati complessi durante la navigazione.
Se i tuoi frammenti passano oggetti complessi come argomenti, valuta la possibilità di rifattorizzare prima il codice, in modo da consentire l'archiviazione e il recupero di questi oggetti dal livello dati. Per esempi, consulta il repository Now in Android.
Limitazioni
Questa sezione descrive le limitazioni attuali di Navigation Compose.
Migrazione incrementale a Navigation Compose
Al momento, non puoi utilizzare Navigation Compose se utilizzi ancora i frammenti come destinazioni nel codice. Per iniziare a utilizzare Navigation Compose, tutte le destinazioni devono essere componibili. Puoi monitorare questa richiesta di funzionalità su Issue Tracker.
Animazioni di transizione
A partire da Navigation 2.7.0-alpha01, il supporto per l'impostazione di transizioni personalizzate, precedentemente da AnimatedNavHost, è ora supportato direttamente in NavHost. Per saperne di più, leggi le note di rilascio.
Scopri di più
Per saperne di più sulla migrazione a Navigation Compose, consulta le seguenti risorse:
- Codelab di Navigation Compose: scopri le nozioni di base di Navigation Compose con un codelab pratico.
- Repository Now in Android: un'app per Android completamente funzionale creata interamente con Kotlin e Jetpack Compose, che segue le best practice di progettazione e sviluppo di Android e include Navigation Compose.
- Migrazione di Sunflower a Jetpack Compose: un blog post che documenta il percorso di migrazione dell'app di esempio Sunflower da View a Compose, che include anche la migrazione a Navigation Compose.
- Jetnews per ogni schermo: un blog post che documenta il refactoring e la migrazione dell'esempio Jetnews per supportare tutti gli schermi con Jetpack Compose e Navigation Compose.
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Navigazione con Compose
- Compose e altre librerie
- Altre considerazioni