Le seguenti sezioni descrivono le strategie per salvare la pila di ritorno e memorizzare lo stato associato alle voci nella pila di ritorno.
Salvare la pila precedente
Garantire la persistenza dello stato di navigazione dell'app in vari eventi del ciclo di vita, tra cui modifiche alla configurazione e interruzioni del processo, è fondamentale per un'esperienza utente positiva. In Navigazione 3, sei tu a possedere la pila di navigazione a ritroso, pertanto non esistono linee guida rigide su come crearla o salvarla. Tuttavia, Navigation 3 offre un metodo pratico che ti fornisce una pila di ritorno salvabile:rememberNavBackStack
.
Utilizza rememberNavBackStack
La funzione componibile rememberNavBackStack
è progettata per creare un back
stack che persiste nelle modifiche alla configurazione e nell'interruzione del processo.
Affinché rememberNavBackStack
funzioni correttamente, ogni chiave nella pila interna deve soddisfare requisiti specifici:
- Implementa l'interfaccia
NavKey
: ogni chiave nello stack di ritorno deve implementare l'interfacciaNavKey
. Questa interfaccia funge da indicatore che segnala alla biblioteca che la chiave può essere salvata. - Disporre dell'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 la pila di ritorno è memorizzarla in un ViewModel
.
Per la persistenza dopo l'interruzione del processo quando utilizzi un ViewModel
o qualsiasi altro
spazio di archiviazione personalizzato, devi:
- Assicurati che le chiavi siano serializzabili: come per
rememberNavBackStack
, le chiavi di navigazione devono essere serializzabili. - Gestisci la serializzazione e la deserializzazione manualmente: sei responsabile di salvare manualmente la rappresentazione serializzata di ogni chiave e deserializzarla dallo spazio di archiviazione permanente (ad es.
SharedPreferences
, un database o un file) quando l'app passa in background o viene ripristinata.
Scoping ViewModel
s to NavEntry
s
ViewModels
vengono utilizzati per mantenere lo stato relativo all'interfaccia utente durante le modifiche alla configurazione, come le rotazioni dello schermo. Per impostazione predefinita, i ViewModels
sono limitati al ViewModelStoreOwner
più vicino, in genere Activity
o Fragment
.
Tuttavia, ti consigliamo di limitare l'ambito di un ViewModel
a un NavEntry
specifico (ad es. una schermata o una destinazione specifica) nella pila precedente, anziché all'intero Activity
. In questo modo, lo stato di ViewModel
viene mantenuto solo mentre
quel determinato ViewModel
fa parte della pila di ritorno e viene cancellato quando
ViewModel
viene estratto.NavEntry
NavEntry
La libreria dei componenti aggiuntivi androidx.lifecycle:lifecycle-viewmodel-navigation3
fornisce un NavEntryDecorator
che semplifica 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 Componi), l'ambito viene automaticamente impostato sulla chiave di quel NavEntry
specifico nello stack precedente. Ciò significa che ViewModel
viene creato quando NavEntry
viene aggiunto allo stack precedente e viene cancellato quando viene rimosso.
Per utilizzare NavEntryDecorator
per limitare l'ambito dei ViewModel
ai NavEntry
, segui questi passaggi:
- Aggiungi la dipendenza
androidx.lifecycle:lifecycle-viewmodel-navigation3
al tuo fileapp/build.gradle.kts
. - Aggiungi
rememberSavedStateNavEntryDecorator()
all'elenco dientryDecorators
durante la costruzione di unNavDisplay
. - Aggiungi altri decorazioni a
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 { }, )