La navigazione descrive il modo in cui gli utenti si spostano all'interno dell'app. Gli utenti interagiscono con gli elementi dell'interfaccia utente, in genere toccandoli o facendo clic su di essi, e l'app risponde visualizzando nuovi contenuti. Se l'utente vuole tornare ai contenuti precedenti, utilizza il gesto Indietro o tocca il pulsante Indietro.
Modellare lo stato di navigazione
Un modo pratico per modellare questo comportamento è utilizzare uno stack di contenuti. Quando l'utente naviga in avanti verso nuovi contenuti, questi vengono inseriti nella parte superiore dello stack. Quando torna indietro da questi contenuti, questi vengono rimossi dallo stack e vengono visualizzati i contenuti precedenti. In termini di navigazione, questo stack viene in genere chiamato back stack perché rappresenta i contenuti a cui l'utente può tornare.
Creare un back stack
In Navigation 3, il back stack non contiene effettivamente contenuti. Contiene invece riferimenti ai contenuti, noti come chiavi. Le chiavi possono essere di qualsiasi tipo, ma in genere sono classi di dati semplici e serializzabili. L'utilizzo di riferimenti anziché di contenuti presenta i seguenti vantaggi:
- È facile navigare inserendo le chiavi nel back stack.
- Se le chiavi sono serializzabili, il back stack può essere salvato in uno spazio di archiviazione permanente, consentendo di sopravvivere alle modifiche della configurazione e alla chiusura del processo. Questo è importante perché gli utenti si aspettano di uscire dall'app, tornarci in un secondo momento e riprendere da dove avevano interrotto con gli stessi contenuti visualizzati. Per maggiori informazioni, consulta Salvare il back stack.
Un concetto chiave dell'API Navigation 3 è che il back stack è di tua proprietà. La libreria:
- Si aspetta che il back stack sia un
List<T>supportato dallo stato dello snapshot, doveTè il tipo dikeysdel back stack. Puoi utilizzareAnyo fornire le tue chiavi con tipi più specifici. Quando vedi i termini "push" o "pop", l'implementazione sottostante consiste nell'aggiungere o rimuovere elementi dalla fine di un elenco. - Osserva il back stack e riflette il suo stato nell'interfaccia utente utilizzando un
NavDisplay.
L'esempio seguente mostra come creare chiavi e un back stack e come modificare il back stack in risposta agli eventi di navigazione dell'utente:
// Define keys that will identify content data object ProductList data class ProductDetail(val id: String) @Composable fun MyApp() { // Create a back stack, specifying the key the app should start with val backStack = remember { mutableStateListOf<Any>(ProductList) } // Supply your back stack to a NavDisplay so it can reflect changes in the UI // ...more on this below... // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state backStack.add(ProductDetail(id = "ABC")) // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state backStack.removeLastOrNull() }
Risolvere le chiavi nei contenuti
I contenuti vengono modellati in Navigation 3 utilizzando NavEntry, una classe
contenente una funzione componibile. Rappresenta una destinazione , ovvero un singolo contenuto
a cui l'utente può navigare in avanti e indietro.
Un NavEntry può contenere anche metadati, ovvero informazioni sui contenuti. Questi metadati possono essere letti da oggetti contenitore, come NavDisplay, per aiutarli a decidere come visualizzare i contenuti di NavEntry. Ad esempio, i metadati possono essere utilizzati per sostituire le animazioni predefinite per un NavEntry specifico. I metadata di NavEntry sono una mappa di chiavi String e valori Any, che fornisce uno spazio di archiviazione dei dati versatile.
Per convertire una key in un NavEntry, crea un provider di voci. Si tratta di una funzione che accetta una key e restituisce un NavEntry per quella key. In genere viene definita come parametro lambda quando si crea un NavDisplay.
Esistono due modi per creare un provider di voci: creando direttamente una funzione lambda
o utilizzando il entryProvider DSL.
Creare direttamente una funzione del provider di voci
In genere, una funzione del provider di voci viene creata utilizzando un'istruzione when, con un ramo per ogni chiave.
entryProvider = { key -> when (key) { is ProductList -> NavEntry(key) { Text("Product List") } is ProductDetail -> NavEntry( key, metadata = mapOf("extraDataKey" to "extraDataValue") ) { Text("Product ${key.id} ") } else -> { NavEntry(Unit) { Text(text = "Invalid Key: $it") } } } }
Utilizzare il DSL entryProvider
Il DSL entryProvider può semplificare la funzione lambda evitando la necessità di eseguire test su ogni tipo di chiave e di creare un NavEntry per ognuna.
A questo scopo, utilizza la funzione di creazione entryProvider. Include anche un comportamento di fallback predefinito (generazione di un errore) se la chiave non viene trovata.
entryProvider = entryProvider { entry<ProductList> { Text("Product List") } entry<ProductDetail>( metadata = mapOf("extraDataKey" to "extraDataValue") ) { key -> Text("Product ${key.id} ") } }
Tieni presente quanto segue nello snippet:
entryviene utilizzato per definire unNavEntrycon il tipo e i contenuti componibili specificatientryaccetta un parametrometadataper impostareNavEntry.metadata
Visualizzare il back stack
Il back stack rappresenta lo stato di navigazione dell'app. Ogni volta che il back stack cambia, l'interfaccia utente dell'app deve riflettere il nuovo stato del back stack. In Navigation 3, un NavDisplay osserva il back stack e aggiorna l'interfaccia utente di conseguenza. Costruiscilo con i seguenti parametri:
- Il back stack, che deve essere di tipo
SnapshotStateList<T>, doveTè il tipo di chiavi del back stack. Si tratta di unListosservabile, quindi attiva la ricomposizione diNavDisplayquando cambia. - Un
entryProviderper convertire le chiavi nel back stack in oggettiNavEntry. - Facoltativamente, fornisci un'espressione lambda al parametro
onBack. Viene chiamata quando l'utente attiva un evento Indietro.
L'esempio seguente mostra come creare un NavDisplay.
data object Home data class Product(val id: String) @Composable fun NavExample() { val backStack = remember { mutableStateListOf<Any>(Home) } NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, entryProvider = { key -> when (key) { is Home -> NavEntry(key) { ContentGreen("Welcome to Nav3") { Button(onClick = { backStack.add(Product("123")) }) { Text("Click to navigate") } } } is Product -> NavEntry(key) { ContentBlue("Product ${key.id} ") } else -> NavEntry(Unit) { Text("Unknown route") } } } ) }
Per impostazione predefinita, NavDisplay mostra il NavEntry più in alto nel back stack in un layout a riquadro singolo. La seguente registrazione mostra l'esecuzione di questa app:
NavDisplay comportamento predefinito con due
destinazioni.Ciclo di vita della destinazione
NavDisplay utilizza personalizzati LifecycleOwners per limitare lo stato del ciclo di vita di un
NavEntry in base ai vincoli a livello di scena e a livello di voce
Per maggiori informazioni sui cicli di vita in Compose, consulta Ciclo di vita in Jetpack Compose.
Vincoli del ciclo di vita a livello di scena
NavDisplay gestisce il ciclo di vita delle Scene attive. I limiti a livello di scena vengono determinati nel seguente modo:
Per le scene non di overlay:
RESUMED: consentito solo quando la transizione della scena è terminata e non sono presenti scene di overlay attive visualizzate sopra di essa.STARTED: limitato aSTARTEDdurante le transizioni della scena, ad esempio quando si naviga in avanti o indietro o quando è coperta da un overlay.
Per le scene di overlay, come finestre di dialogo o fogli inferiori:
RESUMED: consentito solo per la scena di overlay più in alto, attualmente attiva.STARTED: limitato aSTARTEDper le scene di overlay sottostanti coperte da un overlay più recente.
Stato del ciclo di vita a livello di voce
La libreria gestisce lo stato massimo del ciclo di vita di ogni singolo NavEntry in base alla sua presenza nel back stack:
RESUMED: se la voce è presente nel back stack corrente, il suo ciclo di vita può raggiungereRESUMED(soggetto al limite a livello di scena).CREATED: se la voce non è più nel back stack, ad esempio quando è stata rimossa ma viene ancora visualizzata sullo schermo durante l'animazione di uscita, la libreria limita rigorosamente il suo ciclo di vita aCREATED. Questo limite garantisce che le voci in background o in uscita interrompano l'esecuzione di attività attive come la raccolta di flussi o l'avvio di coroutine associate agli statiRESUMEDoSTARTEDmentre completano le transizioni di uscita.
Come si combinano
Ad esempio, lo stato finale del ciclo di vita di un NavEntry viene risolto nel seguente modo:
| Scenario | Limite a livello di scena | Limite a livello di voce | Limite effettivo |
|---|---|---|---|
| Voce attiva, schermo fisso (nessuna transizione o overlay) | RESUMED |
RESUMED |
RESUMED |
| Voce attiva, durante la transizione (navigazione verso o da) | STARTED |
RESUMED |
STARTED |
| Voce attiva, coperta da un overlay (ad esempio, è aperta una finestra di dialogo) | STARTED |
RESUMED |
STARTED |
| Voce rimossa, animazione di uscita | STARTED o RESUMED |
CREATED |
CREATED |
Elaborazione della risposta…
Il seguente diagramma mostra il flusso di dati tra i vari oggetti in Navigation 3:
Gli eventi di navigazione avviano le modifiche. Le chiavi vengono aggiunte o rimosse dal back stack in risposta alle interazioni dell'utente.
La modifica dello stato del back stack attiva il recupero dei contenuti.
NavDisplay(un elemento componibile che esegue il rendering di un back stack) osserva il back stack. Nella configurazione predefinita, mostra la voce del back stack più in alto in un layout a riquadro singolo. Quando la chiave principale del back stack cambia,NavDisplayutilizza questa chiave per richiedere i contenuti corrispondenti al provider di voci.Il provider di voci fornisce i contenuti. Il provider di voci è una funzione che risolve una chiave in un
NavEntry. Dopo aver ricevuto una chiave daNavDisplay, il provider di voci fornisce ilNavEntryassociato, che contiene sia la chiave sia i contenuti.I contenuti vengono visualizzati.
NavDisplayriceve ilNavEntrye visualizza i contenuti.