Stabilité dans Compose

Compose considère les types comme stables ou instables. Un type est stable s'il est immuable ou s'il est possible pour Compose de savoir si sa valeur a changé entre les recompositions. Un type est instable si Compose ne peut pas savoir si sa valeur a changé entre les recompositions.

Compose utilise la stabilité des paramètres d'un composable pour déterminer s'il peut l'ignorer lors de la recomposition:

  • Stable parameters (Paramètres stables) : si un composable possède des paramètres stables qui n'ont pas changé, Compose l'ignore.
  • Paramètres instables:si un composable possède des paramètres instables, Compose le recompose toujours lorsqu'il recompose le parent du composant.

Si votre application inclut de nombreux composants inutilement instables que Compose recompose toujours, vous risquez de rencontrer des problèmes de performances et d'autres problèmes.

Ce document explique comment améliorer la stabilité de votre application pour améliorer les performances et l'expérience utilisateur globale.

Objets immuables

Les extraits de code suivants illustrent les principes généraux sur lesquels reposent la stabilité et la recomposition.

La classe Contact est une classe de données immuable. En effet, tous ses paramètres sont des primitives définies avec le mot clé val. Une fois que vous avez créé une instance de Contact, vous ne pouvez plus modifier la valeur des propriétés de l'objet. Si vous tentez de le faire, vous devez créer un nouvel objet.

data class Contact(val name: String, val number: String)

Le composable ContactRow comporte un paramètre de type Contact.

@Composable
fun ContactRow(contact: Contact, modifier: Modifier = Modifier) {
   var selected by remember { mutableStateOf(false) }

   Row(modifier) {
      ContactDetails(contact)
      ToggleButton(selected, onToggled = { selected = !selected })
   }
}

Réfléchissez à ce qui se passe lorsque l'utilisateur clique sur le bouton d'activation et que l'état selected change:

  1. Compose évalue s'il doit recomposer le code dans ContactRow.
  2. Il constate que le seul argument pour ContactDetails est de type Contact.
  3. Contact étant une classe de données immuable, Compose s'assure qu'aucun des arguments de ContactDetails n'a changé.
  4. Par conséquent, Compose ignore ContactDetails et ne la recompose pas.
  5. D'autre part, les arguments de ToggleButton ont changé et Compose recompose ce composant.

Objets modifiables

Bien que l'exemple précédent utilise un objet immuable, il est possible de créer un objet modifiable. Prenons l'exemple de l'extrait suivant:

data class Contact(var name: String, var number: String)

Comme chaque paramètre de Contact est désormais un var, la classe n'est plus immuable. Si ses propriétés étaient modifiées, Compose n'en serait pas informé. En effet, Compose ne suit que les modifications apportées aux objets State Compose.

Compose considère une telle classe comme instable. Compose n'ignore pas la recomposition des classes instables. Ainsi, si Contact était défini de cette manière, ContactRow dans l'exemple précédent se recomposerait chaque fois que selected changeait.

Implémentation dans Compose

Il peut être utile, bien que ce ne soit pas crucial, de réfléchir à la façon dont Compose détermine précisément les fonctions à ignorer lors de la recomposition.

Lorsque le compilateur Compose s'exécute sur votre code, il marque chaque fonction et chaque type à l'aide de l'une des nombreuses balises. Ces balises reflètent la manière dont Compose gère la fonction ou le type lors de la recomposition.

Fonctions

Compose peut marquer des fonctions comme skippable ou restartable. Notez qu'il peut marquer une fonction comme l'un, les deux ou aucune de ces valeurs:

  • Désactivable: si le compilateur marque un composable comme désactivable, Compose peut l'ignorer lors de la recomposition si tous ses arguments sont égaux à leurs valeurs précédentes.
  • Redémarrable: un composable qui peut être redémarrable sert de "champ d'application" où la recomposition peut commencer. En d'autres termes, la fonction peut être un point d'entrée où Compose peut commencer à réexécuter du code pour la recomposition après un changement d'état.

Types

Compose marque les types comme immuables ou stables. Chaque type correspond à l'un ou à l'autre:

  • Immutable: Compose marque un type comme immuable si la valeur de ses propriétés ne peut jamais changer et si toutes les méthodes sont transparentes sur le plan référentiel.
    • Notez que tous les types primitifs sont marqués comme immuables. Il s'agit, par exemple, de String, Int et Float.
  • Stable: indique un type dont les propriétés peuvent être modifiées après la construction. Si ces propriétés changent au cours de l'exécution, Compose en est informé.

Stabilité au débogage

Si votre application recompose un composable dont les paramètres n'ont pas changé, vérifiez d'abord dans sa définition les paramètres clairement modifiables. Compose recompose toujours un composant si vous transmettez un type avec des propriétés var ou une propriété val qui utilise un type instable connu.

Pour en savoir plus sur le diagnostic des problèmes complexes de stabilité dans Compose, consultez le guide Déboguer la stabilité.

Résoudre les problèmes de stabilité

Pour savoir comment apporter de la stabilité à votre implémentation Compose, consultez le guide Résoudre les problèmes de stabilité.

Résumé

De manière générale, veuillez noter les points suivants:

  • Paramètres: Compose détermine la stabilité de chaque paramètre de vos composables afin de déterminer les composables qu'il doit ignorer lors de la recomposition.
  • Corrections immédiates: si vous remarquez que votre composable n'est pas ignoré et qu'il entraîne un problème de performances, vous devez d'abord vérifier les causes évidentes d'instabilité, comme les paramètres var.
  • Rapports du compilateur: vous pouvez utiliser les rapports de compilation pour déterminer la stabilité déduite de vos classes.
  • Collections: Compose considère toujours les classes de collection comme étant instables, telles que List, Set et Map. En effet, il ne peut pas être garanti qu'ils sont immuables. Vous pouvez utiliser les collections immuables Kotlinx à la place ou annoter vos classes en tant que @Immutable ou @Stable.
  • Autres modules: Compose considère toujours comme instable lorsqu'ils proviennent de modules dans lesquels le compilateur Compose ne s'exécute pas. Encapsulez les classes dans des classes de modèle d'UI, si nécessaire.

Complément d'informations