Si tienes problemas de rendimiento que se deben a una recomposición innecesaria o excesiva, debes depurar la estabilidad de tu app. En esta guía, se describen varios métodos para hacerlo.
Inspector de diseño
El Inspector de diseño de Android Studio te permite ver qué elementos componibles se vuelven a componer en tu app. Muestra los recuentos de cuántas veces Compose volvió a componer o omitió un componente.

Informes del compilador de Compose
El compilador de Compose puede generar los resultados de su inferencia de estabilidad para su inspección. Con este resultado, puedes determinar cuáles de tus funciones de componibilidad se pueden omitir y cuáles no. En las siguientes subsecciones, se resume cómo usar estos informes, pero para obtener información más detallada, consulta la documentación técnica.
Configuración
Los informes del compilador de Compose no están habilitados de forma predeterminada. Puedes activarlas con
una marca del compilador. La configuración exacta varía según tu proyecto, pero, para los proyectos que usan el complemento de Gradle del compilador de Compose, puedes agregar lo siguiente en el archivo build.gradle de cada módulo.
android { ... }
composeCompiler {
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler")
}
Ahora, se generarán informes del compilador de Compose cuando compiles tu proyecto.
Resultado de ejemplo
El reportsDestination genera tres archivos. Los siguientes son resultados de ejemplo de JetSnack.
<modulename>-classes.txt: Es un informe sobre la estabilidad de las clases en este módulo. Muestra.<modulename>-composables.txt: Es un informe sobre cómo se pueden reiniciar y omitir las funciones de componibilidad del módulo. Muestra.<modulename>-composables.csv: Es una versiónCSVdel informe de elementos de componibilidad que puedes importar a una hoja de cálculo o procesar con una secuencia de comandos. Muestra
Informe de elementos componibles
El archivo composables.txt detalla cada función de componibilidad del módulo determinado, incluida la estabilidad de sus parámetros y si se pueden reiniciar o omitir. A continuación, se muestra un ejemplo hipotético 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
)
En este ejemplo, cada parámetro de SnackCollection se marca como stable, por lo que Compose compara cada parámetro con la igualdad estructural (Object.equals()). Si bien los parámetros stable son ideales para valores primitivos y clases de datos pequeñas y planas con verificaciones .equals() económicas, forzar que los modelos que contienen colecciones (como un SnackCollection que une un List<Snack>) sean stable hace que Compose llame a .equals() en cada elemento en cada recomposición. Con el modo de omisión avanzada habilitado, es preferible mantener los modelos que contienen colecciones unstable para que Compose los compare con la igualdad de instancias (===).
Como alternativa, considera otro ejemplo generado con el modo de omisión avanzada inhabilitado:
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
)
Cuando el modo de omisión avanzada está inhabilitado (antes de Kotlin 2.0.20), el elemento componible HighlightedSnacks no se puede omitir. Compose nunca lo omite durante la recomposición, incluso si ninguno de sus parámetros cambió, debido al parámetro unstable snacks.
Con el modo de omisión avanzada habilitado (el valor predeterminado en Kotlin 2.0.20 y versiones posteriores), HighlightedSnacks se marca como skippable, y Compose compara el parámetro unstable snacks con la igualdad de instancias (===). Como resultado, Compose omite HighlightedSnacks si se pasa la misma referencia de List y solo la recompone si se pasa una instancia de List recién asignada.
Informe de clases
El archivo classes.txt contiene un informe similar sobre las clases del módulo determinado. El siguiente fragmento es el resultado de la clase 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
}
Como referencia, la siguiente es la definición 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()
)
El compilador de Compose marcó Snack como inestable. Esto se debe a que el tipo del parámetro tags es Set<String>. Este es un tipo inmutable, dado que no es un MutableSet. Sin embargo, las clases de colección estándar, como Set, List y Map, son, en última instancia, interfaces. Por lo tanto, la implementación subyacente puede seguir siendo mutable.
Por ejemplo, podrías escribir val set: Set<String> = mutableSetOf("foo"). La
variable es constante y su tipo declarado no es mutable, pero su
implementación sí lo es. El compilador de Compose no puede estar seguro de la inmutabilidad de esta clase, ya que solo ve el tipo declarado. Por lo tanto, marca
tags como inestable.