Le sezioni seguenti descrivono le strategie per salvare lo stack indietro e archiviare lo stato associato alle voci dello stack indietro.
Salvare il back stack
Garantire che lo stato di navigazione dell'app persista tra i vari eventi del ciclo di vita, incluse le modifiche alla configurazione e l'interruzione del processo, è fondamentale per una buona esperienza utente. In Navigation 3, lo stack indietro è di tua proprietà, quindi non esistono linee guida rigorose su come crearlo o salvarlo. Tuttavia, Navigation 3 offre
un metodo pratico che ti fornisce un back stack salvabile:
rememberNavBackStack.
Utilizzare rememberNavBackStack
La funzione componibile rememberNavBackStack è progettata per creare uno stack indietro che persiste tra le modifiche alla configurazione e l'interruzione del processo.
Affinché rememberNavBackStack funzioni correttamente, ogni chiave del back stack deve rispettare requisiti specifici:
- Implementare l'interfaccia
NavKey: ogni chiave del back stack deve implementare l'interfacciaNavKey. Questa funge da interfaccia di marcatore che segnala alla libreria che la chiave può essere salvata. - Avere l'annotazione
@Serializable: oltre a implementareNavKey, le classi e gli oggetti chiave devono essere contrassegnati con l'annotazione@Serializable.
Il seguente snippet mostra un'implementazione corretta di rememberNavBackStack:
@Serializable data object Home : NavKey @Composable fun NavBackStack() { val backStack = rememberNavBackStack(Home) }
Ricordare un back stack con sottotipi di NavKey
La funzione componibile rememberNavBackStack restituisce un NavBackStack<NavKey>.
Se la tua app definisce un proprio sottotipo di NavKey da cui ereditano tutte le sue chiavi, puoi conservare la digitazione implementando una funzione di memorizzazione personalizzata, come segue:
@Serializable sealed interface MyAppNavKey : NavKey @Serializable data object ScreenA: MyAppNavKey @Serializable data class ScreenB(val id: String): MyAppNavKey @Composable fun rememberMyAppNavBackStack(vararg elements: MyAppNavKey): NavBackStack<MyAppNavKey> { return rememberSerializable(serializer = serializer()) { NavBackStack(*elements) } } @Composable fun MyApp() { // defaultNavBackStack is NavBackStack<NavKey> val defaultNavBackStack = rememberNavBackStack(ScreenA) // myAppNavBackStack is NavBackStack<MyAppNavKey> val myAppNavBackStack = rememberMyAppNavBackStack(ScreenA) }
Per altri esempi, incluso come gestire il polimorfismo aperto, consulta
NavBackStackSamples.
Alternativa: archiviare in un ViewModel
Un altro approccio alla gestione del back stack è archiviarlo in un ViewModel.
Per la persistenza durante l'interruzione del processo quando utilizzi un ViewModel o qualsiasi altro spazio di archiviazione personalizzato, devi:
- Assicurarti che le chiavi siano serializzabili: proprio come con
rememberNavBackStack, le chiavi di navigazione devono essere serializzabili. - Gestire manualmente la serializzazione e la deserializzazione: quando l'app passa in background o viene ripristinata, devi salvare manualmente la rappresentazione serializzata di ogni chiave nello spazio di archiviazione permanente (ad es.
SharedPreferences, un database o un file) e deserializzarla.
Applicare l'ambito dei ViewModel agli NavEntry
ViewModels vengono utilizzati per conservare lo stato correlato all'UI tra le modifiche alla configurazione,
ad esempio le rotazioni dello schermo. Per impostazione predefinita, ViewModels hanno come ambito il
ViewModelStoreOwner più vicino, in genere Activity o Fragment.
Tuttavia, potresti voler applicare l'ambito di un ViewModel a un NavEntry specifico (ovvero a una schermata o una destinazione specifica) nello stack indietro, anziché all'intera Activity. In questo modo, lo stato di ViewModel viene conservato solo quando il NavEntry specifico fa parte del back stack e viene cancellato quando viene estratto.NavEntry
La libreria di componenti aggiuntivi androidx.lifecycle:lifecycle-viewmodel-navigation3 fornisce
un NavEntryDecorator che facilita questa operazione. Questo decoratore fornisce un ViewModelStoreOwner per ogni NavEntry. Quando crei un ViewModel all'interno dei contenuti di un NavEntry (ad es. utilizzando viewModel() in Compose), il suo ambito viene applicato automaticamente alla chiave NavEntry specifica nel back stack. Ciò significa che ViewModel viene creato quando NavEntry viene aggiunto al back stack e cancellato quando viene rimosso.
Per utilizzare NavEntryDecorator per applicare l'ambito dei ViewModel agli NavEntry, segui
questi passaggi:
- Aggiungi la dipendenza
androidx.lifecycle:lifecycle-viewmodel-navigation3al fileapp/build.gradle.kts. - Aggiungi
rememberSaveableStateHolderNavEntryDecorator()predefinito all'elenco dientryDecoratorsdurante la creazione di unNavDisplay. - Aggiungi
rememberViewModelStoreNavEntryDecorator()all'elenco dientryDecorators.
NavDisplay( entryDecorators = listOf( // Add the default decorators for managing scenes and saving state rememberSaveableStateHolderNavEntryDecorator(), // Then add the view model store decorator rememberViewModelStoreNavEntryDecorator() ), backStack = backStack, entryProvider = entryProvider { }, )