Wenn Leistungsprobleme auftreten, die auf unnötige oder übermäßige Neuzusammensetzungen zurückzuführen sind, sollten Sie die Stabilität Ihrer App debuggen. In diesem Leitfaden werden verschiedene Methoden dafür beschrieben.
Layout-Inspector
Mit dem Layout-Inspektor in Android Studio können Sie sehen, welche zusammensetzbaren Funktionen in Ihrer App neu zusammengesetzt werden. Er zeigt an, wie oft Compose eine Komponente neu zusammengesetzt oder übersprungen hat.

Compilerberichte erstellen
Der Compose-Compiler kann die Ergebnisse seiner Stabilitätsprüfung zur Überprüfung ausgeben. Anhand dieser Ausgabe können Sie feststellen, welche Ihrer Composables übersprungen werden können und welche nicht. In den folgenden Abschnitten wird die Verwendung dieser Berichte zusammengefasst. Ausführlichere Informationen finden Sie in der technischen Dokumentation.
Einrichtung
Compose-Compiler-Berichte sind standardmäßig nicht aktiviert. Sie können sie mit einem Compiler-Flag aktivieren. Die genaue Einrichtung variiert je nach Projekt. Bei Projekten, die das Compose Compiler Gradle-Plug-in verwenden, können Sie der build.gradle-Datei jedes Moduls Folgendes hinzufügen.
android { ... }
composeCompiler {
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler")
}
Compose-Compilerberichte werden jetzt beim Erstellen des Projekts generiert.
Beispielausgabe
reportsDestination gibt drei Dateien aus. Im Folgenden finden Sie Beispielausgaben von JetSnack.
<modulename>-classes.txt: Ein Bericht zur Stabilität von Klassen in diesem Modul. Beispiel.<modulename>-composables.txt: Ein Bericht darüber, wie neustartbar und überspringbar die Composables im Modul sind. Beispiel.<modulename>-composables.csv: EineCSV-Version des Berichts zu zusammensetzbaren Elementen, die Sie in eine Tabelle importieren oder mit einem Skript verarbeiten können. Beispiel
Bericht zu Composables
Die Datei composables.txt enthält Details zu den einzelnen komponierbaren Funktionen für das jeweilige Modul, einschließlich der Stabilität ihrer Parameter und ob sie neu gestartet oder überspringbar sind. Hier ist ein hypothetisches Beispiel von 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
)
In diesem Beispiel ist jeder Parameter von SnackCollection mit stable gekennzeichnet. Compose vergleicht daher jeden Parameter anhand der strukturellen Gleichheit (Object.equals()).
stable-Parameter sind zwar ideal für primitive Werte und kleine, flache Datenklassen mit kostengünstigen .equals()-Prüfungen, aber wenn Sie Modelle mit Sammlungen (z. B. ein SnackCollection, das ein List<Snack> umschließt) als stable deklarieren, ruft Compose bei jeder Neuzusammensetzung .equals() für jedes Element auf. Wenn der Modus für starkes Überspringen aktiviert ist, sollten Sie Modelle, die Sammlungen enthalten, unstable beibehalten, damit Compose sie stattdessen anhand der Instanzgleichheit (===) vergleicht.
Sehen wir uns ein weiteres Beispiel an, das mit deaktiviertem Modus für starkes Überspringen generiert wurde:
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
)
Wenn der Modus „Starkes Überspringen“ deaktiviert ist (vor Kotlin 2.0.20), kann die HighlightedSnacks-Komposition nicht übersprungen werden. Compose überspringt sie bei der Neuzusammensetzung nie, auch wenn sich keiner ihrer Parameter geändert hat, da der unstable-Parameter snacks ist.
Wenn der Modus für starkes Überspringen aktiviert ist (Standardeinstellung in Kotlin 2.0.20 und höher), wird HighlightedSnacks als skippable markiert und Compose vergleicht den unstable-Parameter snacks anhand der Instanzgleichheit (===). Daher überspringt Compose HighlightedSnacks, wenn dieselbe List-Referenz übergeben wird, und führt die Neuzusammensetzung nur aus, wenn eine neu zugewiesene List-Instanz übergeben wird.
Bericht „Kurse“
Die Datei classes.txt enthält einen ähnlichen Bericht zu den Klassen im angegebenen Modul. Das folgende Snippet ist die Ausgabe für die Klasse 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
}
Zur Erinnerung hier die Definition von Snack:
data class Snack(
val id: Long,
val name: String,
val imageUrl: String,
val price: Long,
val tagline: String = "",
val tags: Set<String> = emptySet()
)
Der Compose-Compiler hat Snack als instabil markiert. Das liegt daran, dass der Typ des Parameters tags Set<String> ist. Dies ist ein unveränderlicher Typ, da es sich nicht um einen MutableSet handelt. Standard-Sammlungsklassen wie Set, List und Map sind jedoch letztendlich Schnittstellen. Daher kann die zugrunde liegende Implementierung weiterhin veränderlich sein.
Sie könnten beispielsweise val set: Set<String> = mutableSetOf("foo") schreiben. Die Variable ist konstant und ihr deklarierter Typ ist nicht änderbar, aber ihre Implementierung ist weiterhin änderbar. Der Compose-Compiler kann sich nicht sicher sein, ob diese Klasse unveränderlich ist, da er nur den deklarierten Typ sieht. Daher wird tags als instabil markiert.