Enregistrer et gérer l'état de navigation

Les sections suivantes décrivent des stratégies permettant d'enregistrer votre pile "Retour" et de stocker l'état associé aux entrées de votre pile "Retour".

Enregistrer la pile "Retour"

S'assurer que l'état de navigation de votre application persiste dans les différents événements de cycle de vie, y compris les modifications de configuration et l'arrêt du processus, est essentiel pour une bonne expérience utilisateur. Dans Navigation 3, vous êtes le propriétaire de votre pile "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" pouvant être enregistrée : rememberNavBackStack.

Utiliser rememberNavBackStack

La fonction composable rememberNavBackStack est conçue pour créer une pile "Retour" qui persiste en cas de modification de la configuration et de fin du processus.

Pour que rememberNavBackStack fonctionne correctement, chaque touche de votre pile "Retour" doit respecter des exigences spécifiques:

  • Implémenter l'interface NavKey: chaque touche de la pile "Retour" doit implémenter l'interface NavKey. Il s'agit d'une interface de repère qui signale à la bibliothèque que la clé peut être enregistrée.
  • Disposer de l'annotation @Serializable: en plus d'implémenter NavKey, vos classes et objets clés doivent être marqués avec l'annotation @Serializable.

L'extrait de code suivant montre une implémentation correcte de rememberNavBackStack:

@Serializable
data object Home : NavKey

@Composable
fun NavBackStack() {
    val backStack = rememberNavBackStack(Home)
}

Autre solution: stocker dans un ViewModel

Vous pouvez également gérer votre pile "Retour" en la stockant dans un ViewModel. Pour 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: comme pour 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 un stockage persistant et de sa désérialisation à partir de celui-ci (par exemple, SharedPreferences, une base de données ou un fichier) lorsque votre application passe en arrière-plan ou est restaurée.

Délimiter les ViewModel aux NavEntry

ViewModels permet de conserver l'état lié à l'UI lors des modifications de configuration, telles que les rotations d'écran. Par défaut, les ViewModels sont limitées au ViewModelStoreOwner le plus proche, qui est généralement votre Activity ou Fragment.

Toutefois, vous pouvez limiter un ViewModel à un NavEntry spécifique (c'est-à-dire un écran ou une destination spécifique) sur la pile "Retour", plutôt que l'ensemble de la Activity. Cela garantit que l'état de ViewModel n'est conservé que lorsque ce NavEntry particulier fait partie de la pile "Retour" et est effacé lorsque NavEntry est supprimé.

La bibliothèque de modules complémentaires androidx.lifecycle:lifecycle-viewmodel-navigation3 fournit un NavEntryDecorator qui facilite cela. Ce décorateur fournit un ViewModelStoreOwner pour chaque NavEntry. Lorsque vous créez un ViewModel dans le contenu d'un NavEntry (par exemple, à l'aide de viewModel() dans Compose), son champ d'application est automatiquement limité à la clé de cet NavEntry spécifique sur la pile "Retour". Cela signifie que ViewModel est créé lorsque NavEntry est ajouté à la pile "Retour" et effacé lorsqu'il est supprimé.

Pour utiliser NavEntryDecorator pour définir le champ d'application des ViewModel sur les NavEntry, procédez comme suit:

  1. Ajoutez la dépendance androidx.lifecycle:lifecycle-viewmodel-navigation3 à votre fichier app/build.gradle.kts.
  2. Ajoutez rememberSavedStateNavEntryDecorator() à la liste des entryDecorators lors de la création d'un NavDisplay.
  3. Ajoutez d'autres décorateurs dans 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 { },
)