La navigazione descrive il modo in cui gli utenti si muovono all'interno dell'app. Gli utenti interagiscono con gli elementi dell'interfaccia utente, di solito toccandoli o facendoci clic sopra, e l'app risponde visualizzando nuovi contenuti. Se l'utente vuole tornare ai contenuti precedenti, usa il gesto Indietro o tocca il pulsante Indietro.
Stato di navigazione della modellazione
Un modo pratico per modellare questo comportamento è con una pila di contenuti. Man mano che l'utente avanza verso nuovi contenuti, questi vengono spostati in cima alla pila. Quando tornano indietro da questi contenuti, questi vengono rimossi dalla pila e vengono visualizzati i contenuti precedenti. In termini di navigazione, questo stack viene solitamente chiamato stack indietro perché rappresenta i contenuti a cui l'utente può tornare.

Creare uno stack indietro
In Navigazione 3, lo stack precedente non contiene contenuti. Contiene invece riferimenti ai contenuti, noti come chiavi. Le chiavi possono essere di qualsiasi tipo, ma di solito sono classi di dati semplici e serializzabili. L'utilizzo di riferimenti anziché di contenuti presenta i seguenti vantaggi:
- È facile da navigare premendo i tasti sulla pila posteriore.
- Se le chiavi sono serializzabili, lo stack indietro può essere salvato nello spazio di archiviazione permanente, consentendo di sopravvivere alle modifiche alla configurazione e all'interruzione del processo. Questo è importante perché gli utenti si aspettano di uscire dalla tua app, tornarci in un secondo momento e riprendere da dove avevano interrotto la visualizzazione degli stessi contenuti. Per saperne di più, consulta Salvare lo stack di attività.
Un concetto chiave dell'API Navigation 3 è che lo sviluppatore è proprietario dello stack precedente. La biblioteca:
- Prevede che lo stack precedente sia un
List<T>
supportato dallo stato dello snapshot, doveT
è il tipo di stack precedentekeys
. Puoi utilizzareAny
o fornire chiavi più fortemente tipizzate. Quando vedi i termini "push" o "pop", l'implementazione sottostante consiste nell'aggiungere o rimuovere elementi dalla fine di un elenco. - Osserva lo stack precedente e riflette il suo stato nell'UI utilizzando un
NavDisplay
.
L'esempio seguente mostra come creare chiavi e uno stack indietro e modificare lo stack indietro 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 i problemi relativi alle chiavi dei 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ò avanzare e tornare 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 ignorare le animazioni predefinite per un NavEntry
specifico. NavEntry
metadata
è una mappa di chiavi String
e valori Any
, che fornisce un versatile archivio
di dati.
Per convertire un key
in un NavEntry
, crea un fornitore di voci. Questa è una
funzione che accetta un key
e restituisce un NavEntry
per quel key
. Viene
in genere definito come parametro lambda durante la creazione di un NavDisplay
.
Esistono due modi per creare un fornitore di voci: creando direttamente una funzione Lambda o utilizzando il linguaggio specifico del dominio (DSL) entryProvider
.
Crea direttamente una funzione del fornitore di voci
In genere, crei una funzione Entry Provider utilizzando un'istruzione when
, con
un ramo per ciascuna delle tue chiavi.
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") } } } }
Utilizza il linguaggio specifico del dominio entryProvider
Il entryProvider
DSL può semplificare la tua funzione lambda evitando la necessità
di eseguire test su ciascun tipo di chiave e di creare un NavEntry
per ognuno.
A questo scopo, utilizza la funzione di creazione entryProvider
. Include anche il 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} ") } }
Nota quanto segue dallo snippet:
entry
viene utilizzato per definire unNavEntry
con il tipo e i contenuti componibili specificatientry
accetta un parametrometadata
per impostareNavEntry.metadata
Visualizzare lo stack precedente
Lo stack indietro rappresenta lo stato di navigazione dell'app. Ogni volta che lo stack indietro
cambia, la UI dell'app deve riflettere il nuovo stato dello stack indietro. In Navigazione 3, un
NavDisplay
osserva lo stack precedente e aggiorna la relativa UI. Costruiscila
con i seguenti parametri:
- Lo stack precedente, che deve essere di tipo
SnapshotStateList<T>
, doveT
è il tipo di chiavi dello stack precedente. È unList
osservabile, quindi attiva la ricomposizione diNavDisplay
quando cambia. - Un
entryProvider
per convertire le chiavi nello stack precedente in oggettiNavEntry
. - Se vuoi, fornisci una lambda al parametro
onBack
. Viene chiamato quando l'utente attiva un evento Indietro.
Il seguente esempio 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 primo NavEntry
dello stack precedente in un layout a
un solo riquadro. La seguente registrazione mostra l'app in esecuzione:

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

Gli eventi di navigazione avviano le modifiche. Le chiavi vengono aggiunte o rimosse dallo stack precedente in risposta alle interazioni dell'utente.
La modifica dello stato dello stack indietro attiva il recupero dei contenuti.
NavDisplay
(un composable che esegue il rendering di uno stack precedente) osserva lo stack precedente. Nella sua configurazione predefinita, mostra la voce più in alto dello stack delle attività in un layout a un solo riquadro. Quando la chiave superiore della pila posteriore cambia,NavDisplay
utilizza questa chiave per richiedere i contenuti corrispondenti al fornitore della voce.Il fornitore della voce fornisce i contenuti. Il fornitore di voci è una funzione che risolve una chiave in un
NavEntry
. Dopo aver ricevuto una chiave daNavDisplay
, il fornitore della voce fornisce ilNavEntry
associato, che contiene sia la chiave sia i contenuti.Vengono visualizzati i contenuti. Il
NavDisplay
riceve ilNavEntry
e visualizza i contenuti.