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

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

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

Инспектор макетов в Android Studio позволяет вам увидеть, какие компонуемые элементы перекомпоновываются в вашем приложении. Он отображает количество раз, сколько раз 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.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 полностью перезапускаемая, пропускаемая и стабильная. Как правило, это предпочтительно, хотя и не обязательно.

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

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 как нестабильные.