Diagnozowanie problemów ze stabilnością

Jeśli zauważysz problemy z wydajnością wynikające z niepotrzebnego lub nadmiernego ponownego komponowania, musisz debugować stabilność aplikacji. W tym przewodniku znajdziesz kilka metod, które Ci w tym pomogą.

[narzędzie] Layout Inspector

Inspektor układu w Android Studio pozwala sprawdzić, które funkcje kompozycyjne są ponownie komponowane w aplikacji. Wyświetla on liczbę ponownych kompozycji lub pominięć komponentu przez Compose.

Ponowne komponowanie i liczba pominięć w narzędziu Layout Inspector

Tworzenie raportów kompilatora

Kompilator Compose może wyświetlać wyniki wnioskowania o stabilności do sprawdzenia. Na podstawie tych danych możesz określić, które funkcje kompozycyjne można pominąć, a których nie. W podsekcjach poniżej znajdziesz podsumowanie informacji o tym, jak korzystać z tych raportów. Więcej szczegółów znajdziesz w dokumentacji technicznej.

Konfiguracja

Raporty kompilatora Compose nie są domyślnie włączone. Możesz je aktywować za pomocą flagi kompilatora. Dokładna konfiguracja zależy od projektu, ale w przypadku projektów korzystających z wtyczki Gradle kompilatora Compose możesz dodać poniższy kod w pliku build.gradle każdego modułu.

  android { ... }

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

Podczas kompilowania projektu będą teraz generowane raporty kompilatora Compose.

Przykładowe dane wyjściowe

Funkcja reportsDestination zwraca 3 pliki. Poniżej przedstawiamy przykładowe dane wyjściowe z JetSnack.

  • <modulename>-classes.txt: raport o stabilności klas w tym module. Próbka
  • <modulename>-composables.txt: raport o tym, czy funkcje kompozycyjne w module można ponownie uruchamiać i pomijać. Próbka
  • <modulename>-composables.csv:CSVwersja raportu o komponentach, którą możesz zaimportować do arkusza kalkulacyjnego lub przetworzyć za pomocą skryptu. Próbka

Raport funkcji kompozycyjnych

Plik composables.txt zawiera szczegółowe informacje o każdej funkcji kompozycyjnej w danym module, w tym stabilność jej parametrów oraz to, czy można ją ponownie uruchomić lub pominąć. Oto hipotetyczny przykład z 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
)

Ten komponent SnackCollection można w pełni ponownie uruchomić, pominąć i jest on stabilny. Jest to zazwyczaj preferowane, ale nie jest obowiązkowe.

Z drugiej strony spójrzmy na inny przykład.

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
)

Funkcji HighlightedSnacks nie można pominąć. Compose nigdy nie pomija tego elementu podczas ponownego komponowania. Dzieje się tak nawet wtedy, gdy żaden z parametrów nie uległ zmianie. Przyczyną jest parametr unstable, snacks.

Raport Zajęcia

Plik classes.txt zawiera podobny raport dotyczący klas w danym module. Poniższy fragment to dane wyjściowe klasy 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
}

Dla przypomnienia podajemy definicję Snack:

data class Snack(
    val id: Long,
    val name: String,
    val imageUrl: String,
    val price: Long,
    val tagline: String = "",
    val tags: Set<String> = emptySet()
)

Kompilator Compose oznaczył Snack jako niestabilny. Dzieje się tak, ponieważ typ parametru tags to Set<String>. Jest to typ niezmienny, ponieważ nie jest to MutableSet. Standardowe klasy kolekcji, takie jak Set, ListMap, są jednak interfejsami. Dlatego bazowa implementacja może być nadal modyfikowalna.

Możesz na przykład napisać val set: Set<String> = mutableSetOf("foo"). Zmienna jest stała, a jej zadeklarowany typ jest niezmienny, ale jej implementacja nadal może ulegać zmianom. Komplilator Compose nie ma pewności, czy ta klasa jest niezmienna, ponieważ widzi tylko zadeklarowany typ. Dlatego oznacza tags jako niestabilny.