Le sezioni seguenti descrivono le strategie per salvare lo stack precedente e memorizzare lo stato associato alle voci dello stack precedente.
Salvare lo stack di navigazione
Garantire che lo stato di navigazione dell'app persista in vari eventi del ciclo di vita,
inclusi modifiche alla configurazione e interruzione del processo, è fondamentale per una buona esperienza utente. In Navigation 3, lo stack precedente è di tua proprietà, quindi non esistono linee guida rigide
su come crearlo o salvarlo. Tuttavia, Navigation 3 offre
un metodo pratico che ti fornisce uno stack indietro salvabile:
rememberNavBackStack.
Utilizza rememberNavBackStack
La funzione componibile rememberNavBackStack è progettata per creare uno stack
che persiste in caso di modifiche alla configurazione e interruzione del processo.
Affinché rememberNavBackStack funzioni correttamente, ogni chiave nello stack precedente
deve rispettare requisiti specifici:
- Implementa l'interfaccia
NavKey: ogni chiave nello stack precedente deve implementare l'interfacciaNavKey. che 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) }
Alternativa: archiviazione in un ViewModel
Un altro approccio per gestire lo stack di navigazione è memorizzarlo in un ViewModel.
Per la persistenza in caso di interruzione del processo quando utilizzi ViewModel o qualsiasi altro
spazio di archiviazione personalizzato, devi:
- Assicurati che le chiavi siano serializzabili: proprio come con
rememberNavBackStack, le chiavi di navigazione devono essere serializzabili. - Gestisci manualmente la serializzazione e la deserializzazione: sei responsabile del salvataggio manuale della rappresentazione serializzata di ogni chiave e della sua deserializzazione dallo spazio di archiviazione permanente (ad es.
SharedPreferences, un database o un file) quando l'app passa in background o viene ripristinata.
Scoping ViewModels to NavEntrys
ViewModels vengono utilizzati per mantenere lo stato relativo all'interfaccia utente in seguito a modifiche alla configurazione,
come le rotazioni dello schermo. Per impostazione predefinita, gli ViewModels sono limitati all'ViewModelStoreOwner più vicino, che in genere è il tuo Activity o Fragment.
Tuttavia, potresti voler limitare un ViewModel a un NavEntry specifico (ad es. una
schermata o una destinazione specifica) nello stack precedente, anziché all'intero
Activity. In questo modo, lo stato di ViewModel viene mantenuto solo mentre
NavEntry fa parte dello stack precedente e viene cancellato quando
NavEntry viene rimosso.
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 Composizione), l'ambito viene automaticamente limitato alla chiave di quel NavEntry specifico nello stack precedente. Ciò significa che l'ViewModel viene creato quando l'NavEntry viene aggiunto allo stack precedente e
cancellato quando viene rimosso.
Per utilizzare NavEntryDecorator per definire l'ambito delle ViewModel in base alle NavEntry, segui questi
passaggi:
- Aggiungi la dipendenza
androidx.lifecycle:lifecycle-viewmodel-navigation3al fileapp/build.gradle.kts. - Aggiungi
rememberSaveableStateHolderNavEntryDecorator()all'elenco dientryDecoratorsquando crei unNavDisplay. - Aggiungi altri decoratori al tuo
NavDisplay.
NavDisplay( entryDecorators = listOf( // Add the default decorators for managing scenes and saving state rememberSceneSetupNavEntryDecorator(), rememberSavedStateNavEntryDecorator(), // Then add the view model store decorator rememberViewModelStoreNavEntryDecorator() ), backStack = backStack, entryProvider = entryProvider { }, )