Esegui la migrazione di Jetpack Navigation a Navigation Compose

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 dell'interfaccia utente basata sulle visualizzazioni a Jetpack Compose.

Prerequisiti per la migrazione

Puoi eseguire la migrazione a Scrittura navigazione quando sei in grado di sostituire tutti i frammenti con i componenti componibili dello schermo corrispondenti. Gli elementi componibili dello schermo possono contenere un mix di contenuti di Compose e View, ma tutte le destinazioni di navigazione devono essere componibili per consentire la migrazione di Navigation Compose. Fino ad allora, devi continuare a utilizzare il componente di navigazione basato su frammenti nei codebase Visualizzazione di interoperabilità e Compose. Per ulteriori informazioni, consulta la documentazione sull'interoperabilità di navigazione.

L'utilizzo di Navigation Compose in un'app solo per Compose non è un prerequisito. Puoi continuare a utilizzare il componente di navigazione basato su frammenti, a condizione di mantenere i frammenti per ospitare i tuoi contenuti componibili.

Passaggi della 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 componibili dello schermo, in cui i frammenti agiscono solo come contenitori componibili. In questa fase, puoi eseguire la migrazione a Scrittura navigazione.

Se la tua app segue già un pattern di progettazione delle funzioni definite dall'utente e la nostra guida all'architettura, la migrazione a Jetpack Compose e Navigation Compose non dovrebbe richiedere importanti refactoring di altri livelli dell'app, a parte il livello UI.

Per eseguire la migrazione a Scrittura Navigazione, segui questi passaggi:

  1. Aggiungi la dipendenza di Compose per la navigazione all'app.
  2. Crea un componibile App-level e aggiungilo a Activity come punto di contatto di Compose, sostituendo la configurazione del layout Visualizza:

    class SampleActivity : ComponentActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample)
            setContent {
                SampleApp(/* ... */)
            }
        }
    }

  3. Imposta NavController in una posizione che abbia accesso a tutti gli elementi componibili che devono farvi riferimento (di solito all'interno dell'elemento componibile App). Questo approccio segue i principi dell'alzata di stato e ti consente di utilizzare NavController come fonte attendibile per la navigazione tra schermate componibili e il mantenimento dello stack di base:

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
        // ...
    }

  4. Crea il NavHost dell'app all'interno dell'app componibile e trasmetti navController:

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
    
        SampleNavHost(navController = navController)
    }
    
    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = "first") {
            // ...
        }
    }

  5. Aggiungi le destinazioni composable per creare il tuo grafico di navigazione. Se in precedenza è stata eseguita la migrazione di ogni schermata a Compose, questo passaggio consiste solo nell'estrazione di questi elementi componibili delle schermate dai frammenti nelle composable destinazioni:

    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(/* ... */)
            }
            // ...
        }
    }

  6. Se hai seguito le indicazioni relative all'architettura dell'interfaccia utente di Compose, nello specifico alla modalità di trasferimento degli eventi ViewModel e degli eventi di navigazione agli elementi componibili, il passaggio successivo consiste nel modificare il modo in cui fornisci il ViewModel a ogni schermata componibile. Spesso puoi utilizzare Hilt injection e il relativo punto di integrazione con Compose e Navigation tramite hiltViewModel:

    @Composable
    fun FirstScreen(
        // viewModel: FirstViewModel = viewModel(),
        viewModel: FirstViewModel = hiltViewModel(),
        onButtonClick: () -> Unit = {},
    ) {
        // ...
    }

  7. Sostituisci tutte le chiamate di navigazione findNavController() con quelle navController e trasmettile come eventi di navigazione a ogni schermata componibile, anziché passare l'intero navController. Questo approccio segue le best practice di esposizione degli eventi da funzioni componibili ai chiamanti e mantiene navController come unica fonte attendibile.

    1. Se hai già utilizzato il plug-in Safe Args per generare indicazioni e azioni di navigazione, sostituiscilo con un route, ovvero un percorso di stringa del componibile univoco per ogni destinazione.
    2. Per sostituire gli argomenti sicuri durante la trasmissione di dati, consulta Navigare con gli argomenti.
    3. Per la sicurezza dei tipi in Scrittura navigazione, leggi la sezione Argomenti sicuri di seguito.

      @Composable
      fun SampleNavHost(
          navController: NavHostController
      ) {
          NavHost(navController = navController, startDestination = "first") {
              composable("first") {
                  FirstScreen(
                      onButtonClick = {
                          // findNavController().navigate(firstScreenToSecondScreenAction)
                          navController.navigate("second_screen_route")
                      }
                  )
              }
              composable("second") {
                  SecondScreen(
                      onIconClick = {
                          // findNavController().navigate(secondScreenToThirdScreenAction)
                          navController.navigate("third_screen_route")
                      }
                  )
              }
              // ...
          }
      }

  8. Rimuovi tutti i frammenti, i layout XML pertinenti, la navigazione non necessaria e altre risorse, nonché le dipendenze Fragment e Jetpack Navigation obsolete.

Gli stessi passaggi sono disponibili con ulteriori dettagli relativi a Scrittura di navigazione nella documentazione della configurazione.

Casi d'uso comuni

Indipendentemente dal componente di navigazione utilizzato, si applicano gli stessi principi di navigazione.

Ecco alcuni casi d'uso comuni per la migrazione:

Per informazioni più dettagliate su questi casi d'uso, vedi Navigazione con Scrivi.

Safe Args

A differenza di Jetpack Navigation, Navigation Compose non supporta l'utilizzo del plug-in SafeArgs per la generazione del codice. Puoi ottenere la sicurezza dei tipi con Navigation Compose strutturando il tuo codice in modo da renderlo sicuro dal tipo in fase di runtime.

Recupera dati complessi durante la navigazione

Navigation Compose è basato sul routing tramite stringhe e, a differenza di Jetpack Navigation, non supporta il trasferimento di parametri come Parcelables e Serializables personalizzati,.

Ti consigliamo vivamente di non trasferire oggetti di dati complessi durante la navigazione. Passa invece il numero minimo di informazioni necessarie, come un identificatore univoco o un'altra forma di ID, come argomenti quando esegui azioni di navigazione. Dovresti archiviare oggetti complessi come dati in un'unica fonte attendibile, ad esempio il livello dati. Per ulteriori informazioni, consulta Recupero di dati complessi durante la navigazione.

Se i tuoi frammenti passano oggetti complessi come argomenti, valuta la possibilità di eseguire prima il refactoring del codice in modo che permetta l'archiviazione e il recupero di questi oggetti dal livello dati. Per alcuni esempi, consulta il repository Ora in Android.

Limitazioni

In questa sezione vengono descritte le limitazioni attuali di Scrittura Navigazione.

Migrazione incrementale a Navigation Compose

Al momento, non puoi utilizzare Scrittura navigazione mentre continui a usare i frammenti come destinazioni nel codice. Per iniziare a utilizzare Navigation Compose, tutte le destinazioni devono essere componibili. Puoi tenere traccia di questa richiesta di funzionalità nel Tracker dei problemi.

Animazioni delle transizioni

A partire da Navigatore 2.7.0-alpha01, il supporto per l'impostazione di transizioni personalizzate, in precedenza da AnimatedNavHost, è ora supportato direttamente in NavHost. Per ulteriori informazioni, leggi le note di rilascio.

Scopri di più

Per ulteriori informazioni sulla migrazione a Scrittura navigazione, consulta le seguenti risorse:

  • Codelab di Navigation Compose: apprendi le nozioni di base di Navigation Compose con un codelab pratico.
  • Ora nel repository 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 post del blog che documenta il percorso di migrazione dell'app di esempio Sunflower da Views a Compose, che include anche la migrazione a Navigation Compose.
  • Jetnews per ogni schermo: un post del blog che documenta il refactoring e la migrazione dell'esempio di Jetnews per supportare tutti gli schermi con Jetpack Compose e Navigation Compose.