Диагностика проблем со стабильностью

Если у вас возникли проблемы с производительностью, вызванные ненужной или чрезмерной рекомпозицией, вам следует отладить стабильность вашего приложения. В этом руководстве описывается несколько методов для этого.

Инспектор макетов

Layout Inspector в Android Studio позволяет вам увидеть, какие компонуемые элементы перекомпоновываются в вашем приложении. Он отображает количество раз, когда Compose перекомпоновывал или пропускал компонент.

Рекомпозиция и количество пропусков в инспекторе макетов

Составление отчетов компилятора

Компилятор Compose может выводить результаты своего вывода стабильности для проверки. Используя этот вывод, вы можете определить, какие из ваших компонуемых объектов являются пропускаемыми, а какие — нет. В следующих подразделах кратко изложено, как использовать эти отчеты, но для более подробной информации см. техническую документацию .

Настраивать

Отчеты компилятора Compose по умолчанию не включены. Вы можете активировать их с помощью флага компилятора. Точная настройка зависит от вашего проекта, но для проектов, использующих плагин Gradle компилятора Compose, вы можете добавить следующее в файл build.gradle каждого модуля.

  android { ... }

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

Отчеты компилятора Compose теперь будут создаваться при сборке вашего проекта.

Пример вывода

reportsDestination выводит три файла. Ниже приведены примеры выходных данных из JetSnack .

  • <modulename>-classes.txt : Отчет о стабильности классов в этом модуле. Пример .
  • <modulename>-composables.txt : Отчет о том, насколько перезапускаемы и пропускаемы компонуемые элементы в модуле. Пример .
  • <modulename>-composables.csv : CSV -версия отчета composables, которую можно импортировать в электронную таблицу или обрабатывать с помощью скрипта. Пример

Отчет Composables

Файл composables.txt содержит подробную информацию о каждой компонуемой функции для данного модуля, включая стабильность их параметров и то, являются ли они перезапускаемыми или пропускаемыми. Ниже приведен гипотетический пример из 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
)

Этот SnackCollection composable полностью перезапускаемый, пропускаемый и стабильный. Это обычно предпочтительно, хотя, конечно, не обязательно.

С другой стороны, давайте рассмотрим другой пример.

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
)

Компонуемый элемент HighlightedSnacks не может быть пропущен. Compose никогда не пропускает его во время повторной компоновки. Это происходит, даже если ни один из его параметров не изменился. Причиной этого является unstable параметр snacks .

Отчет о классах

Файл classes.txt содержит аналогичный отчет по классам в данном модуле. Следующий фрагмент — это вывод для класса 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
}

Для справки, ниже приводится определение Snack :

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

Компилятор Compose пометил Snack как нестабильный. Это связано с тем, что тип параметра tagsSet<String> . Это неизменяемый тип, поскольку он не является MutableSet . Однако стандартные классы коллекций, такие как Set , List и Map в конечном счете являются интерфейсами. Таким образом, базовая реализация может быть все еще изменяемой.

Например, можно написать val set: Set<String> = mutableSetOf("foo") . Переменная является константой, а ее объявленный тип не является изменяемым, но ее реализация все еще является изменяемой. Компилятор Compose не может быть уверен в неизменности этого класса, поскольку он видит только объявленный тип. Поэтому он помечает tags как нестабильные.