Diagnostiquer les problèmes de stabilité

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.

Décompte des recompositions et des recompositions ignorées dans l'outil d'inspection de la mise en page

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.

Configurer

Les rapports du compilateur ne sont pas activés par défaut. Vous pouvez les activer à l'aide d'un indicateur de compilation La configuration idéale dépend de votre projet, mais vous pouvez coller le script suivant, pour la plupart des projets, dans votre fichier racine build.gradle.

Groovy

subprojects {
  tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
        kotlinOptions {
            if (project.findProperty("composeCompilerReports") == "true") {
                freeCompilerArgs += [
                        "-P",
                        "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" +
                                project.buildDir.absolutePath + "/compose_compiler"
                ]
            }
            if (project.findProperty("composeCompilerMetrics") == "true") {
                freeCompilerArgs += [
                        "-P",
                        "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" +
                                project.buildDir.absolutePath + "/compose_compiler"
                ]
            }
        }
    }
}

Kotlin

subprojects {
    tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
        kotlinOptions {
            if (project.findProperty("composeCompilerReports") == "true") {
                freeCompilerArgs += listOf(
                    "-P",
                    "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${project.buildDir.absolutePath}/compose_compiler"
                )
            }
            if (project.findProperty("composeCompilerMetrics") == "true") {
                freeCompilerArgs += listOf(
                    "-P",
                    "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=${project.buildDir.absolutePath}/compose_compiler"
                )
            }
        }
    }
}

Exécuter la tâche

Pour débugger la stabilité de vos composables, exécutez la tâche comme suit :

./gradlew assembleRelease -PcomposeCompilerReports=true

Exemple de résultat

Cette tâche 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 version CSV du 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
)

Ce composable SnackCollection est entièrement redémarrable, ignorable et stable. Ce qui est généralement préférable, mais pas obligatoire.

Prenons un autre exemple.

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
)

Le composable HighlightedSnacks n'est pas ignorable. Compose ne l'ignore jamais lors de la recomposition. Cela se produit même si aucun de ses paramètres n'a été modifié. La raison vient du paramètre unstable, snacks.

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 standard 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.