En las siguientes secciones, se describen estrategias para guardar la pila de actividades y almacenar el estado asociado con las entradas de la pila de actividades.
Guarda tu 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 el cierre del proceso, es fundamental para brindar una buena experiencia del usuario. En Navigation 3, eres el 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 de conveniencia que te proporciona una pila de actividades que se puede guardar: rememberNavBackStack.
Usar 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 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) }
Recuerda una pila de actividades con subtipos de NavKey
La función de componibilidad rememberNavBackStack devuelve un NavBackStack<NavKey>.
Si tu app define su propio subtipo de NavKey del que heredan todas sus claves, puedes conservar ese tipo implementando una función de recordatorio personalizada, de la siguiente manera:
@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) }
Para obtener más ejemplos, incluido cómo controlar el polimorfismo abierto, consulta
NavBackStackSamples.
Alternativa: Almacenamiento en un ViewModel
Otro enfoque para administrar tu pila de actividades es almacenarla en un ViewModel.
Para lograr la persistencia durante el cierre del proceso cuando se usa un ViewModel o cualquier otro almacenamiento personalizado, debes hacer lo siguiente:
- Asegúrate de que tus claves se puedan serializar: Al igual que con
rememberNavBackStack, tus claves de navegación deben poder serializarse. - Controla la serialización y deserialización de forma manual: Eres responsable de
guardar manualmente la representación serializada de cada clave en el almacenamiento persistente (p.ej.,
SharedPreferences, una base de datos o un archivo) y deserializarla desde allí cuando tu app pase a segundo plano o se restablezca.
Cómo definir el alcance de las instancias de ViewModel para los objetos NavEntry
Los ViewModels se usan para retener el estado relacionado con la IU durante los cambios de configuración, como las rotaciones de pantalla. De forma predeterminada, los ViewModels se limitan al ViewModelStoreOwner más cercano, que suele ser tu Activity o Fragment.
Sin embargo, es posible que desees definir el alcance de un ViewModel para un NavEntry específico (es decir, una pantalla o un destino específicos) en la pila de actividades, en lugar de todo el Activity. Esto garantiza que el estado de ViewModel se conserve solo mientras ese NavEntry en particular forme parte de la pila de actividades y se borre cuando se quite el NavEntry.
La biblioteca de complementos androidx.lifecycle:lifecycle-viewmodel-navigation3 proporciona un NavEntryDecorator que facilita este proceso. Este decorador proporciona un ViewModelStoreOwner para cada NavEntry. Cuando creas un ViewModel dentro del contenido de un NavEntry (p.ej., usando viewModel() en Compose), se limita automáticamente a la clave de ese NavEntry específico en la pila de actividades. Esto significa que el ViewModel se crea cuando se agrega el NavEntry a la pila de actividades y se borra cuando se quita.
Para usar NavEntryDecorator con el objetivo de definir el alcance de los ViewModel en los NavEntry, sigue
estos pasos:
- Agrega la dependencia
androidx.lifecycle:lifecycle-viewmodel-navigation3al archivoapp/build.gradle.kts. - Agrega el
rememberSaveableStateHolderNavEntryDecorator()predeterminado a la lista deentryDecoratorscuando construyas unNavDisplay. - Agrega
rememberViewModelStoreNavEntryDecorator()a la lista deentryDecorators.
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 { }, )