La navigazione descrive il modo in cui gli utenti si spostano nella tua app. Gli utenti interagiscono con gli elementi dell'interfaccia utente, di solito toccandoli o facendoci clic sopra, e l'app risponde mostrando nuovi contenuti. Se l'utente vuole tornare ai contenuti precedenti, usa il gesto Indietro o tocca il pulsante Indietro.
Modellazione dello stato di navigazione
Un modo pratico per modellare questo comportamento è utilizzare una serie di contenuti. Quando l'utente avanza verso nuovi contenuti, questi vengono inseriti in cima alla serie. Quando torna indietro, i contenuti vengono rimossi dall'elenco e vengono visualizzati quelli precedenti. In termini di navigazione, questa serie è in genere indicata come back stack perché rappresenta i contenuti a cui l'utente può tornare.

Creare una pila di ritorno
In Navigazione 3, la pila di navigazione non contiene effettivamente contenuti. Al loro interno sono contenuti riferimenti ai contenuti, noti come chiavi. Le chiavi possono essere di qualsiasi tipo, ma solitamente sono classi di dati semplici e serializzabili. L'utilizzo di riferimenti anziché di contenuti presenta i seguenti vantaggi:
- È facile navigare premendo i tasti sulla serie di tasti Indietro.
- Se le chiavi sono serializzabili, la pila di ritorno può essere salvata in un archiviazione permanente, il che consente di sopravvivere alle modifiche alla configurazione e all'interruzione del processo. Questo è importante perché gli utenti si aspettano di uscire dalla tua app, di tornarci più tardi e di riprendere da dove avevano interrotto con gli stessi contenuti visualizzati. Per saperne di più, consulta Salvare la pila Indietro.
Un concetto chiave dell'API Navigation 3 è che sei il proprietario della pila di navigazione a ritroso. La biblioteca:
- Si prevede che lo stack di ritorno sia un
List<T>
basato sullo stato snapshot, doveT
è il tipo di stack di ritornokeys
. Puoi utilizzareAny
o fornire le tue chiavi con tipi più forti. Quando vedi i termini "push" o "pop", l'implementazione sottostante consiste nell'aggiungere o rimuovere elementi dalla fine di un elenco. - Osserva la pila di ritorno e ne riflette lo stato nell'interfaccia utente utilizzando un
NavDisplay
.
L'esempio seguente mostra come creare chiavi e una pila di navigazione e modificarla 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 ai 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ò andare e tornare.
Un NavEntry
può contenere anche metadati, ovvero informazioni sui contenuti. Questi
metadati possono essere letti dagli oggetti contenitore, come NavDisplay
, per aiutarli
a decidere come visualizzare i contenuti di NavEntry
. Ad esempio, i metadati possono essere utilizzati per eseguire l'override delle animazioni predefinite per un NavEntry
specifico. NavEntrymetadata
è una mappa di chiavi String
a valori Any
, che fornisce un versatile archiviazione dei dati.
Per convertire un key
in un NavEntry
, crea un entryProvider
. Si tratta di una funzione che accetta un key
e restituisce un NavEntry
per quel key
. Generalmente viene definito come parametro lambda durante la creazione di un NavDisplay
.
Esistono due modi per creare un entryProvider
: creando direttamente una funzione lambda o utilizzando il DSL entryProvider
.
Creare direttamente una funzione entryProvider
In genere, crei una funzione entryProvider
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 di dover eseguire il test su ciascun tipo di chiave e di creare un NavEntry
per ogni tipo.
A tale scopo, utilizza la funzione di compilatore entryProvider
. Include anche il comportamento di riserva predefinito (l'emissione 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 dallo snippet:
entry
viene utilizzato per definire unNavEntry
con il tipo e i contenuti composable specificatientry
accetta un parametrometadata
per impostareNavEntry.metadata
Mostra la pila precedente
La pila di navigazione rappresenta lo stato di navigazione dell'app. Ogni volta che la pila di app inferiore cambia, l'interfaccia utente dell'app deve riflettere il nuovo stato della pila di app inferiore. In Navigazione 3, un
NavDisplay
osserva la pila di ritorno e aggiorna la relativa UI di conseguenza. Costruiscilo con i seguenti parametri:
- La pila di ritorno, che deve essere di tipo
SnapshotStateList<T>
, doveT
è il tipo di chiavi della pila di ritorno. È unList
osservabile, quindi attiva la ricostituzione diNavDisplay
quando cambia. - Un
entryProvider
per convertire le chiavi nello stack di ritorno inNavEntry
. - Se vuoi, specifica una funzione lambda per il parametro
onBack
. Viene chiamato quando l'utente attiva un evento di ritorno.
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 nella pila precedente in un layout a riquadro singolo. La registrazione seguente mostra questa app in esecuzione:

NavDisplay
con due
destinazioni.Riassumendo
Il seguente diagramma mostra il flusso dei dati tra i vari oggetti in Navigation 3:

Gli eventi di navigazione avviano le modifiche. Le chiavi vengono aggiunte o rimosse dalla pila di ritorno in risposta alle interazioni dell'utente.
La modifica dello stato della pila posteriore attiva il recupero dei contenuti.
NavDisplay
(un composable che esegue il rendering di una pila di app di ritorno) osserva la pila di app di ritorno. Nella configurazione predefinita, mostra la voce della pila di ritorno più in alto in un layout a riquadro singolo. Quando la chiave superiore nella pila posteriore cambia,NavDisplay
utilizza questa chiave per richiedere i contenuti corrispondenti al fornitore di voci.Il fornitore di voci fornisce i contenuti. Il provider di voci è una funzione che risolve una chiave in un
NavEntry
. Dopo aver ricevuto una chiave dalNavDisplay
, il fornitore di voci fornisce ilNavEntry
associato, che contiene sia la chiave sia i contenuti.I contenuti vengono visualizzati.
NavDisplay
riceveNavEntry
e visualizza i contenuti.