Les sections suivantes décrivent les stratégies permettant d'enregistrer votre pile de retour et de stocker l'état associé aux entrées de votre pile de retour.
Enregistrer votre pile "Retour"
Il est essentiel de s'assurer que l'état de navigation de votre application persiste lors de divers événements du cycle de vie, y compris les modifications de configuration et l'arrêt du processus, pour offrir une bonne expérience utilisateur. Dans Navigation 3, vous êtes propriétaire de votre pile de retour. Il n'existe donc pas de consignes strictes sur la façon de la créer ou de l'enregistrer. Toutefois, Navigation 3 propose une méthode pratique qui vous fournit une pile "Retour" enregistrable : rememberNavBackStack.
Utiliser rememberNavBackStack
La fonction composable rememberNavBackStack est conçue pour créer une pile de retour qui persiste en cas de modification de la configuration et de fin du processus.
Pour que rememberNavBackStack fonctionne correctement, chaque clé de votre pile de retour doit respecter des exigences spécifiques :
- Implémentez l'interface
NavKey: chaque clé de la pile "Retour" doit implémenter l'interfaceNavKey. Il s'agit d'une interface de marqueur qui indique à la bibliothèque que la clé peut être enregistrée. - Avoir l'annotation
@Serializable: en plus d'implémenterNavKey, vos classes et objets clés doivent être marqués avec l'annotation@Serializable.
L'extrait suivant montre une implémentation correcte de rememberNavBackStack :
@Serializable data object Home : NavKey @Composable fun NavBackStack() { val backStack = rememberNavBackStack(Home) }
Autre solution : stocker les données dans un ViewModel
Une autre approche pour gérer votre pile "Retour" consiste à la stocker dans un ViewModel.
Pour assurer la persistance en cas d'arrêt du processus lorsque vous utilisez un ViewModel ou tout autre stockage personnalisé, vous devez :
- Assurez-vous que vos clés sont sérialisables : tout comme avec
rememberNavBackStack, vos clés de navigation doivent être sérialisables. - Gérer manuellement la sérialisation et la désérialisation : vous êtes responsable de l'enregistrement manuel de la représentation sérialisée de chaque clé dans le stockage persistant (par exemple,
SharedPreferences, une base de données ou un fichier) lorsque votre application passe en arrière-plan ou est restaurée.
Définition de la portée de ViewModel à NavEntry s
Les ViewModels sont utilisés pour conserver l'état lié à l'UI lors des modifications de configuration, telles que les rotations d'écran. Par défaut, les ViewModels sont limités au ViewModelStoreOwner le plus proche, qui est généralement votre Activity ou Fragment.
Toutefois, vous pouvez limiter la portée d'un ViewModel à un NavEntry spécifique (c'est-à-dire un écran ou une destination spécifique) dans la pile de retour, plutôt qu'à l'ensemble de Activity. Cela garantit que l'état de ViewModel n'est conservé que lorsque ce NavEntry particulier fait partie de la pile "Retour", et qu'il est effacé lorsque le NavEntry est retiré.
La bibliothèque de modules complémentaires androidx.lifecycle:lifecycle-viewmodel-navigation3 fournit un NavEntryDecorator qui facilite cette opération. Ce décorateur fournit un ViewModelStoreOwner pour chaque NavEntry. Lorsque vous créez un ViewModel dans le contenu d'un NavEntry (par exemple, en utilisant viewModel() dans Compose), il est automatiquement limité à la clé de ce NavEntry spécifique dans la pile de retour. Cela signifie que ViewModel est créé lorsque NavEntry est ajouté à la pile "Retour" et effacé lorsqu'il est supprimé.
Pour utiliser NavEntryDecorator afin de définir la portée des ViewModel sur les NavEntry, procédez comme suit :
- Ajoutez la dépendance
androidx.lifecycle:lifecycle-viewmodel-navigation3à votre fichierapp/build.gradle.kts. - Ajoutez
rememberSaveableStateHolderNavEntryDecorator()à la liste desentryDecoratorslorsque vous créez unNavDisplay. - Ajoutez d'autres décorateurs à votre
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 { }, )