Stabilitätsprobleme diagnostizieren

Wenn Leistungsprobleme auftreten, die auf unnötige oder übermäßige Neukomposition zurückzuführen sind, sollten Sie die Stabilität Ihrer App debuggen. In dieser Anleitung werden verschiedene Methoden dafür beschrieben.

Layout Inspector

Mit dem Layout Inspector in Android Studio können Sie sehen, welche Composables in Ihrer App neu zusammengesetzt werden. Er zeigt an, wie oft Compose eine Komponente neu zusammengesetzt oder übersprungen hat.

Anzahl der Neukompositionen und Überspringungen im Layout Inspector

Berichte des Compose-Compilers

Der Compose-Compiler kann die Ergebnisse seiner Stabilitätsanalyse zur Überprüfung ausgeben. Anhand dieser Ausgabe können Sie feststellen, welche Ihrer Composables übersprungen werden können und welche nicht. In den folgenden Unterabschnitten wird zusammengefasst, wie Sie diese Berichte verwenden. Weitere Informationen finden Sie in der technischen Dokumentation.

Einrichtung

Berichte des Compose-Compilers 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 Gradle-Plug-in des Compose-Compilers verwenden, können Sie in der Datei build.gradle jedes Moduls Folgendes hinzufügen.

  android { ... }

  composeCompiler {
    reportsDestination = layout.buildDirectory.dir("compose_compiler")
    metricsDestination = layout.buildDirectory.dir("compose_compiler")
  }

Berichte des Compose-Compilers werden jetzt beim Erstellen Ihres Projekts generiert.

Beispielausgabe

Die 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 dazu, wie oft die Composables im Modul neu gestartet und übersprungen werden können. Beispiel.
  • <modulename>-composables.csv:Eine CSV Version des Berichts zu Composables 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 angegebene Modul, einschließlich der Stabilität ihrer Parameter und ob sie neu gestartet oder überspringbar sind. Im Folgenden finden Sie ein hypothetisches Beispiel aus 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
)

Dieses SnackCollection-Composable kann vollständig neu gestartet und übersprungen werden und ist stabil. Das ist im Allgemeinen vorzuziehen, aber nicht zwingend erforderlich.

Alternativ können Sie sich ein anderes Beispiel ansehen.

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
)

Das HighlightedSnacks-Composable kann nicht übersprungen werden. Compose überspringt es bei der Neukomposition nie. Das geschieht auch dann, wenn sich keiner der Parameter geändert hat. Der Grund dafür ist der unstable-Parameter snacks.

Bericht zu Klassen

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 Referenz finden Sie 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. Da es sich nicht um ein MutableSet handelt, ist dies ein unveränderlicher Typ. Standardmäßige 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 veränderlich, aber ihre Implementierung ist immer noch veränderlich. Der Compose-Compiler kann sich nicht sicher sein, dass diese Klasse unveränderlich ist, da er nur den deklarierten Typ sieht. Daher markiert er tags als instabil.