Si vous rencontrez des problèmes de performance dus à une recomposition inutile ou excessive, vous devez vérifier la stabilité de votre application. Ce guide présente plusieurs méthodes pour y parvenir.
Outil d'inspection de la mise en page
L'outil d'inspection de la mise en page dans Android Studio vous permet de voir quels composables se recomposent dans votre application. Il affiche le nombre de fois où Compose a recomposé ou ignoré un composant.

Rapports du compilateur Compose
Le compilateur compose peut afficher les résultats de son inférence de stabilité à des fins d'inspection. Ainsi, vous pouvez déterminer lesquels de vos composables peuvent être ignorés, et ceux qui ne peuvent pas l'être. Les sous-sections suivantes résument la manière d'utiliser ces rapports. Pour obtenir des informations plus détaillées, consultez la section documentation technique.
Configuration
Les rapports du compilateur Compose ne sont pas activés par défaut. Vous pouvez les activer à l'aide d'un indicateur de compilation La configuration exacte varie en fonction de votre projet, mais pour les projets utilisant le plug-in Gradle du compilateur Compose, vous pouvez ajouter ce qui suit dans le fichier build.gradle de chaque module.
android { ... }
composeCompiler {
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler")
}
Les rapports du compilateur Compose seront désormais générés lors de la compilation de votre projet.
Exemple de résultat :
reportsDestination génère trois fichiers. Les fichiers suivants sont des exemples de résultats pour JetSnack.
<modulename>-classes.txt: un rapport sur la stabilité des classes dans ce module. Exemple.<modulename>-composables.txt: un rapport sur le niveau de redémarrage et d'ignorance des composables dans le module. Exemple.<modulename>-composables.csv: une versionCSVdu rapport sur les composables que vous pouvez importer dans une feuille de calcul ou traiter à l'aide d'un script. Exemple
Rapport sur les composables
Le fichier composables.txt détaille chaque fonction composable pour le module donné, y compris la stabilité des paramètres et si elles sont redémarrables ou ignorables. Ci-dessous un exemple hypothétique de JetSnack :
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun SnackCollection(
stable snackCollection: SnackCollection
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
stable index: Int = @static 0
stable highlight: Boolean = @static true
)
Dans cet exemple, chaque paramètre de SnackCollection est marqué comme stable. Compose compare donc chaque paramètre à l'aide de l'égalité structurelle (Object.equals()). Bien que les paramètres stable soient parfaits pour les valeurs primitives et les petites classes de données plates avec des vérifications .equals() peu coûteuses, forcer les modèles contenant des collections (comme un SnackCollection qui encapsule un List<Snack>) à être stable amène Compose à appeler .equals() sur chaque élément à chaque recomposition. Lorsque le mode de désactivation forcée est activé, il est préférable de conserver les modèles contenant des collections unstable afin que Compose les compare en utilisant l'égalité d'instance (===).
Voici un autre exemple généré avec le mode de saut renforcé désactivé :
restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
stable index: Int
unstable snacks: List<Snack>
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
)
Lorsque le mode de désactivation forcée est désactivé (avant Kotlin 2.0.20), le composable HighlightedSnacks ne peut pas être ignoré. Compose ne l'ignore jamais lors de la recomposition, même si aucun de ses paramètres n'a changé, en raison du paramètre unstable snacks.
Lorsque le mode de désactivation forcée est activé (par défaut dans Kotlin 2.0.20 et versions ultérieures), HighlightedSnacks est marqué comme skippable, et Compose compare le paramètre unstable snacks à l'aide de l'égalité d'instance (===). Par conséquent, Compose ignore HighlightedSnacks si la même référence List est transmise et ne la recompose que si une instance List nouvellement allouée est transmise.
Rapport sur les classes
Le fichier classes.txt contient un rapport similaire sur les classes du module donné. L'extrait de code suivant est la sortie pour les classes Snack :
unstable class Snack {
stable val id: Long
stable val name: String
stable val imageUrl: String
stable val price: Long
stable val tagline: String
unstable val tags: Set<String>
<runtime stability> = Unstable
}
À titre indicatif, l'extrait suivant est la définition de Snack :
data class Snack(
val id: Long,
val name: String,
val imageUrl: String,
val price: Long,
val tagline: String = "",
val tags: Set<String> = emptySet()
)
Le compilateur Compose a marqué Snack comme étant instable. Cela s'explique par le fait que le type de paramètre tags est Set<String>. Il s'agit d'un type immuable, étant donné que ce n'est pas un MutableSet. Cependant, les classes de collection standards telles que Set, List et Map sont en réalité des interfaces. Ainsi, l'implémentation sous-jacente peut toujours être mutable.
Vous pouvez par exemple écrire val set: Set<String> = mutableSetOf("foo"). La variable est constante et son type déclaré n'est pas mutable, contrairement à son implémentation qui est toujours mutable. Le compilateur Compose ne peut pas être sûr de l'immutabilité de cette classe, car il ne voit que le type déclaré. C'est pourquoi il marque tags comme étant instable.