En las siguientes secciones, se describen estrategias para guardar la pila de actividades y almacenar el estado asociado con las entradas de la pila.
Cómo guardar la pila de actividades
Garantizar que el estado de navegación de tu app persista en varios eventos del ciclo de vida, incluidos los cambios de configuración y la finalización del proceso, es fundamental para brindar una buena experiencia del usuario. En Navigation 3, eres propietario de tu pila de actividades, por lo que no hay lineamientos estrictos sobre cómo debes crearla o guardarla. Sin embargo, Navigation 3 ofrece un método conveniente que te proporciona una pila de actividades que se puede guardar: rememberNavBackStack
.
Usa rememberNavBackStack
La función de componibilidad rememberNavBackStack
está diseñada para crear una pila de actividades que persista en los cambios de configuración y el cierre del proceso.
Para que rememberNavBackStack
funcione correctamente, cada clave de tu pila de actividades debe cumplir con requisitos específicos:
- Implementa la interfaz
NavKey
: Cada clave de la pila de actividades debe implementar la interfazNavKey
. Esto actúa como una interfaz de marcador que le indica a la biblioteca que se puede guardar la clave. - Tener la anotación
@Serializable
: Además de implementarNavKey
, tus clases y objetos clave deben estar marcados con la anotación@Serializable
.
En el siguiente fragmento, se muestra una implementación correcta de rememberNavBackStack
:
@Serializable data object Home : NavKey @Composable fun NavBackStack() { val backStack = rememberNavBackStack(Home) }
Alternativa: Almacenamiento en un ViewModel
Otro enfoque para administrar tu pila de actividades es almacenarla en un ViewModel
.
Para mantener la persistencia a través del cierre de procesos cuando usas un ViewModel
o cualquier otro almacenamiento personalizado, debes hacer lo siguiente:
- Asegúrate de que tus claves sean serializables: Al igual que con
rememberNavBackStack
, tus claves de navegación deben ser serializables. - Controla la serialización y la deserialización de forma manual: Eres responsable de guardar de forma manual la representación serializada de cada clave en el almacenamiento persistente y deserializarla desde allí (p.ej.,
SharedPreferences
, una base de datos o un archivo) cuando tu app pasa a segundo plano o se restaura.
Alcance de ViewModel
a NavEntry
ViewModels
se usan para retener el estado relacionado con la IU en todos los cambios de configuración, como las rotaciones de pantalla. De forma predeterminada, ViewModels
se limita al ViewModelStoreOwner
más cercano, que suele ser tu Activity
o Fragment
.
Sin embargo, te recomendamos que definas el alcance de un ViewModel
a un NavEntry
específico (es decir, una pantalla o un destino específicos) en la pila de actividades, en lugar de a todo el Activity
. Esto garantiza que el estado de ViewModel
se retenga solo mientras ese NavEntry
en particular forme parte de la pila de actividades y se borre cuando se quite NavEntry
.
La biblioteca de complementos androidx.lifecycle:lifecycle-viewmodel-navigation3
proporciona
un NavEntryDecorator
que facilita esto. Este decorador proporciona un ViewModelStoreOwner
para cada NavEntry
. Cuando creas un ViewModel
dentro del contenido de un NavEntry
(p.ej., con viewModel()
en Compose), se asigna automáticamente al alcance de esa clave específica de NavEntry
en la pila de actividades. Esto significa que ViewModel
se crea cuando se agrega NavEntry
a la pila de actividades y se borra cuando se quita.
Para usar NavEntryDecorator
para asignar ViewModel
a NavEntry
, sigue estos pasos:
- Agrega la dependencia
androidx.lifecycle:lifecycle-viewmodel-navigation3
a tu archivoapp/build.gradle.kts
. - Agrega
rememberSavedStateNavEntryDecorator()
a la lista deentryDecorators
cuando crees unNavDisplay
. - Agrega otros decoradores a tu
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 { }, )