La navigation décrit la façon dont les utilisateurs se déplacent dans votre application. Ils interagissent avec les éléments de l'interface utilisateur, généralement en appuyant ou en cliquant dessus, et l'application répond en affichant un nouveau contenu. Si l'utilisateur souhaite revenir au contenu précédent, il utilise le geste Retour ou appuie sur le bouton Retour.
Modéliser l'état de navigation
Une façon pratique de modéliser ce comportement consiste à utiliser une pile de contenu. Lorsque l'utilisateur navigue vers l'avant vers un nouveau contenu, celui-ci est placé en haut de la pile. Lorsqu'il revient en arrière, le contenu est retiré de la pile et le contenu précédent s'affiche. En termes de navigation, cette pile est généralement appelée pile "Retour" , car elle représente le contenu auquel l'utilisateur peut revenir.
Créer une pile "Retour"
Dans Navigation 3, la pile "Retour" ne contient pas de contenu. Elle contient plutôt des références au contenu, appelées clés. Les clés peuvent être de n'importe quel type, mais il s'agit généralement de classes de données sérialisables simples. L'utilisation de références plutôt que de contenu présente les avantages suivants :
- Il est simple de naviguer en plaçant des clés dans la pile "Retour".
- Tant que les clés sont sérialisables, la pile "Retour" peut être enregistrée dans un stockage persistant, ce qui lui permet de survivre aux modifications de configuration et à la fin du processus. Ceci est important, car les utilisateurs s'attendent à pouvoir quitter votre application, y revenir plus tard et reprendre là où ils s'étaient arrêtés, avec le même contenu affiché. Pour en savoir plus, consultez Enregistrer votre pile "Retour".
Un concept clé de l'API Navigation 3 est que vous possédez la pile "Retour". La bibliothèque :
- s'attend à ce que votre pile "Retour" soit un
List<T>sauvegardé par un état d'instantané, oùTest le type de voskeysde pile "Retour". Vous pouvez utiliserAnyou fournir vos propres clés plus fortement typées. Lorsque vous voyez les termes "push" ou "pop", l'implémentation sous-jacente consiste à ajouter ou à supprimer des éléments à la fin d'une liste. - observe votre pile "Retour" et reflète son état dans l'UI à l'aide d'un
NavDisplay.
L'exemple suivant montre comment créer des clés et une pile "Retour", et comment modifier la pile "Retour" en réponse aux événements de navigation de l'utilisateur :
// Define keys that will identify content data object ProductList data class ProductDetail(val id: String) @Composable fun MyApp() { // Create a back stack, specifying the key the app should start with val backStack = remember { mutableStateListOf<Any>(ProductList) } // Supply your back stack to a NavDisplay so it can reflect changes in the UI // ...more on this below... // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state backStack.add(ProductDetail(id = "ABC")) // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state backStack.removeLastOrNull() }
Résoudre les clés en contenu
Le contenu est modélisé dans Navigation 3 à l'aide de NavEntry, qui est une classe
contenant une fonction composable. Il représente une destination , un élément unique
de contenu vers lequel l'utilisateur peut naviguer vers l'avant et vers l'arrière.
Un NavEntry peut également contenir des métadonnées, c'est-à-dire des informations sur le contenu. Ces métadonnées peuvent être lues par des objets conteneurs, tels que NavDisplay, pour les aider à décider comment afficher le contenu de NavEntry. Par exemple, les métadonnées peuvent être utilisées pour remplacer les animations par défaut d'un NavEntry spécifique. Les metadata de NavEntry sont une carte de clés String vers des valeurs Any, ce qui permet un stockage de données polyvalent.
Pour convertir une key en NavEntry, créez un fournisseur d'entrées. Il s'agit d'une fonction qui accepte une key et renvoie un NavEntry pour cette key. Elle est généralement définie comme paramètre lambda lors de la création d'un NavDisplay.
Il existe deux façons de créer un fournisseur d'entrées : en créant directement une fonction lambda
ou en utilisant le entryProvider DSL.
Créer directement une fonction de fournisseur d'entrées
Vous créez généralement une fonction de fournisseur d'entrées à l'aide d'une instruction when, avec une branche pour chacune de vos clés.
entryProvider = { key -> when (key) { is ProductList -> NavEntry(key) { Text("Product List") } is ProductDetail -> NavEntry( key, metadata = mapOf("extraDataKey" to "extraDataValue") ) { Text("Product ${key.id} ") } else -> { NavEntry(Unit) { Text(text = "Invalid Key: $it") } } } }
Utiliser le DSL entryProvider
Le DSL entryProvider peut simplifier votre fonction lambda en évitant d'avoir à tester chaque type de clé et à construire un NavEntry pour chacun d'eux.
Pour ce faire, utilisez la fonction de compilation entryProvider. Elle inclut également un comportement de secours par défaut (générer une erreur) si la clé n'est pas trouvée.
entryProvider = entryProvider { entry<ProductList> { Text("Product List") } entry<ProductDetail>( metadata = mapOf("extraDataKey" to "extraDataValue") ) { key -> Text("Product ${key.id} ") } }
Notez les points suivants dans l'extrait :
entrypermet de définir unNavEntryavec le type et le contenu composable donnés.entryaccepte un paramètremetadatapour définirNavEntry.metadata.
Afficher la pile "Retour"
La pile "Retour" représente l'état de navigation de votre application. Chaque fois que la pile "Retour" change, l'UI de l'application doit refléter le nouvel état de la pile "Retour". Dans Navigation 3, un NavDisplay observe votre pile "Retour" et met à jour son UI en conséquence. Construisez-le avec les paramètres suivants :
- Votre pile "Retour" doit être de type
SnapshotStateList<T>, oùTest le type de vos clés de pile "Retour". Il s'agit d'uneListobservable qui déclenche la recomposition deNavDisplaylorsqu'elle change. - Un
entryProviderpour convertir les clés de votre pile "Retour" en objetsNavEntry. - Vous pouvez également fournir un lambda au paramètre
onBack. Il est appelé lorsque l'utilisateur déclenche un événement de retour.
L'exemple suivant montre comment créer un NavDisplay.
data object Home data class Product(val id: String) @Composable fun NavExample() { val backStack = remember { mutableStateListOf<Any>(Home) } NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, entryProvider = { key -> when (key) { is Home -> NavEntry(key) { ContentGreen("Welcome to Nav3") { Button(onClick = { backStack.add(Product("123")) }) { Text("Click to navigate") } } } is Product -> NavEntry(key) { ContentBlue("Product ${key.id} ") } else -> NavEntry(Unit) { Text("Unknown route") } } } ) }
Par défaut, le NavDisplay affiche le NavEntry le plus haut de la pile "Retour" dans une mise en page à un seul volet. L'enregistrement suivant montre l'exécution de cette application :
NavDisplay comportement par défaut avec deux
destinations.Cycle de vie de la destination
NavDisplay utilise des custom LifecycleOwners personnalisés pour limiter l'état du cycle de vie d'un
NavEntry en fonction des contraintes au niveau de la Scene et de l'entrée
contraintes.
Pour en savoir plus sur les cycles de vie dans Compose, consultez Cycle de vie dans Jetpack Compose.
Contraintes de cycle de vie au niveau de la scène
NavDisplay gère le cycle de vie des Scene actifs. Les limites au niveau de la scène sont déterminées comme suit :
Pour les scènes sans superposition :
RESUMED: autorisé uniquement lorsque la transition de scène est terminée et qu'aucune scène de superposition active ne s'affiche au-dessus.STARTED: limité àSTARTEDpendant les transitions de scène, par exemple lors d'une navigation vers l'avant ou vers l'arrière, ou lorsqu'il est couvert par une superposition.
Pour les scènes de superposition, telles que les boîtes de dialogue ou les feuilles inférieures :
RESUMED: autorisé uniquement pour la scène de superposition active la plus haute.STARTED: limité àSTARTEDpour toutes les scènes de superposition sous-jacentes couvertes par une superposition plus récente.
État du cycle de vie au niveau de l'entrée
La bibliothèque gère l'état maximal du cycle de vie de chaque NavEntry en fonction de sa présence dans la pile "Retour" :
RESUMED: si l'entrée est présente dans la pile "Retour" actuelle, son cycle de vie peut atteindreRESUMED(sous réserve de la limite au niveau de la scène).CREATED: si l'entrée ne se trouve plus dans la pile "Retour", par exemple lorsqu'elle a été retirée, mais qu'elle est toujours affichée à l'écran pendant l' animation de sortie, la bibliothèque limite strictement son cycle de vie àCREATED. Cette limite garantit que les entrées en arrière-plan ou en sortie cessent d'exécuter des tâches actives telles que la collecte de flux ou le lancement de coroutines liées aux étatsRESUMEDouSTARTEDpendant qu'elles terminent leurs transitions de sortie.
Combinaison
Par exemple, l'état final du cycle de vie d'un NavEntry est résolu comme suit :
| Scénario | Limite au niveau de la scène | Limite au niveau de l'entrée | Limite effective |
|---|---|---|---|
| Entrée active, écran fixe (aucune transition ni superposition) | RESUMED |
RESUMED |
RESUMED |
| Entrée active, pendant la transition (navigation vers ou depuis) | STARTED |
RESUMED |
STARTED |
| Entrée active, couverte par une superposition (par exemple, une boîte de dialogue est ouverte) | STARTED |
RESUMED |
STARTED |
| Entrée retirée, animation de sortie | STARTED ou RESUMED |
CREATED |
CREATED |
Synthèse
Le schéma suivant montre comment les données circulent entre les différents objets de Navigation 3 :
Les événements de navigation initient des modifications. Des clés sont ajoutées ou supprimées de la pile "Retour" en réponse aux interactions de l'utilisateur.
La modification de l'état de la pile "Retour" déclenche la récupération du contenu. Le
NavDisplay(un composable qui affiche une pile "Retour") observe la pile "Retour". Dans sa configuration par défaut, il affiche l'entrée de pile "Retour" la plus haute dans une mise en page à un seul volet. Lorsque la clé supérieure de la pile "Retour" change, leNavDisplayutilise cette clé pour demander le contenu correspondant au fournisseur d'entrées.Le fournisseur d'entrées fournit le contenu. Le fournisseur d'entrées est une fonction qui résout une clé en
NavEntry. Lorsqu'il reçoit une clé duNavDisplay, le fournisseur d'entrées fournit leNavEntryassocié, qui contient à la fois la clé et le contenu.Le contenu s'affiche. Le
NavDisplayreçoit leNavEntryet affiche le contenu.