Stabilitätsprobleme diagnostizieren

Wenn Sie Leistungsprobleme haben, die auf unnötige oder übermäßige Neuzusammenstellungen 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 Inspector in Android Studio können Sie sehen, welche Composables in Ihrer App neu zusammengesetzt werden. Außerdem wird angezeigt, wie oft Compose eine Komponente neu zusammengesetzt oder übersprungen hat.

Anzahl der Neukompositionen und Überspringungen im Layout Inspector

Compilerberichte erstellen

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

Einrichten

Compose-Compilerberichte sind nicht standardmäßig aktiviert. Sie können sie mit einem Compiler-Flag aktivieren. Die genaue Einrichtung variiert je nach Projekt. Bei Projekten, die das Gradle-Plug-in für den Compose-Compiler verwenden, können Sie Folgendes in die build.gradle-Datei jedes Moduls einfügen.

  android { ... }

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

Beim Erstellen Ihres Projekts werden jetzt Compose-Compilerberichte generiert.

Beispielausgabe:

Der reportsDestination gibt drei Dateien aus. Hier sind einige 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 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 jeder zusammensetzbaren Funktion für das angegebene Modul, einschließlich der Stabilität ihrer Parameter und ob sie neu gestartet oder übersprungen werden können. 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
)

Diese SnackCollection-Composable ist vollständig neu startbar, überspringbar und stabil. Das ist im Allgemeinen vorzuziehen, aber nicht zwingend erforderlich.

Sehen wir uns ein anderes Beispiel an.

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 nie bei der Neuzusammensetzung. Dies geschieht auch dann, wenn sich keiner der Parameter geändert hat. Der Grund dafür ist der Parameter unstable, snacks.

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. Da es sich nicht um ein MutableSet handelt, ist es ein unveränderlicher Typ. Standardmäßige Sammlungsklassen wie Set, List und Map sind jedoch letztendlich Schnittstellen. Die zugrunde liegende Implementierung kann also weiterhin geändert werden.

Sie können beispielsweise val set: Set<String> = mutableSetOf("foo") schreiben. Die Variable ist konstant und ihr deklarierter Typ ist nicht veränderbar, aber ihre Implementierung ist weiterhin veränderbar. Der Compose-Compiler kann die Unveränderlichkeit dieser Klasse nicht sicher bestimmen, da er nur den deklarierten Typ sieht. Daher wird tags als instabil gekennzeichnet.