Оптимизация иерархии макетов

Попробуйте способ создания композиций.
Jetpack Compose — это рекомендуемый набор инструментов для создания пользовательского интерфейса для Android. Узнайте, как работать с макетами в Compose.

Распространенное заблуждение заключается в том, что использование базовых структур компоновки приводит к наиболее эффективным макетам. Однако каждый виджет и макет, добавляемый в приложение, требует инициализации, компоновки и отрисовки. Например, использование вложенных экземпляров LinearLayout может привести к чрезмерно глубокой иерархии представлений. Кроме того, вложенность нескольких экземпляров LinearLayout , использующих параметр layout_weight , может быть особенно затратной, поскольку каждый дочерний элемент необходимо измерять дважды. Это особенно важно, когда макет создается многократно, например, при использовании в RecyclerView .

В этом документе показано, как использовать инспектор макета и линтер для проверки и оптимизации макета.

Проверьте свою планировку.

В состав инструментов Android SDK входит инструмент Layout Inspector , который позволяет анализировать макет во время работы приложения. Использование этого инструмента помогает выявить неэффективность в работе макета.

Инструмент Layout Inspector позволяет выбирать запущенные процессы на подключенном устройстве или эмуляторе, а затем отображать дерево компоновки. Светофоры на каждом блоке отображают его производительность по измерениям, компоновке и отрисовке, помогая выявлять потенциальные проблемы.

Например, на рисунке 1 показан макет, используемый в качестве элемента в RecyclerView . Этот макет отображает небольшое растровое изображение слева и два расположенных друг над другом текстовых элемента справа. Особенно важно оптимизировать подобные макеты, которые создаются несколько раз, поскольку это многократно увеличивает преимущества в производительности.

Изображение, показывающее один элемент списка: одно изображение и два вертикально выровненных текста.
Рисунок 1. Концептуальная компоновка элемента в RecyclerView .

Инспектор компоновки отображает список доступных устройств и работающих с ними компонентов. Выберите нужный компонент на вкладке «Окна» и нажмите «Инспектор компоновки», чтобы просмотреть иерархию компоновки выбранного компонента. Например, на рисунке 2 показана компоновка элемента списка, изображенного на рисунке 1.

Изображение, демонстрирующее инспектор компоновки и композицию LinearLayout.
Рисунок 2. Иерархия компоновки для макета на рисунке 1, использующая вложенные экземпляры LinearLayout .

Пересмотрите свою компоновку.

Поскольку производительность предыдущей компоновки снижается из-за вложенного LinearLayout , вы можете повысить производительность, сделав компоновку плоской — другими словами, сделав ее пологой и широкой, а не узкой и глубокой. ConstraintLayout в качестве корневого узла позволяет использовать такие компоновки. При преобразовании этой схемы для использования ConstraintLayout компоновка становится двухуровневой иерархией:

    <androidx.constraintlayout.widget.ConstraintLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      android:id="@+id/root"
      android:layout_width="match_parent"
      android:layout_height="52dp"
      android:background="#e4e6e4"
      android:padding="4dp">

      <ImageView
          android:id="@+id/image"
          android:layout_width="48dp"
          android:layout_height="48dp"
          android:background="#5c5c74"
          android:contentDescription="An example box"
          app:layout_constraintBottom_toBottomOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />

      <TextView
          android:id="@+id/title"
          android:layout_width="0dp"
          android:layout_height="0dp"
          android:layout_marginStart="4dp"
          android:background="#745c74"
          app:layout_constraintBottom_toTopOf="@+id/subtitle"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintStart_toEndOf="@id/image"
          app:layout_constraintTop_toTopOf="parent" />

      <TextView
          android:id="@+id/subtitle"
          android:layout_width="0dp"
          android:layout_height="0dp"
          android:background="#7e8d6e"
          app:layout_constraintBottom_toBottomOf="parent"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintStart_toStartOf="@id/title"
          app:layout_constraintTop_toBottomOf="@+id/title" />
  </androidx.constraintlayout.widget.ConstraintLayout>
    

Осмотр новой планировки выглядит следующим образом:

Изображение, демонстрирующее инспектор 3D-макетов.
Рисунок 3. Трехмерный режим инспектора компоновки.

Преимущества такого подхода многократно возрастают, поскольку подобная структура используется для каждого элемента списка.

Большая часть различий обусловлена ​​использованием layout_weight в дизайне LinearLayout , что может замедлить измерение. Это один из примеров того, как каждый макет имеет свои преимущества. Тщательно обдумайте, необходимо ли использовать параметр layout_weight.

В некоторых сложных схемах система может тратить ресурсы на измерение одного и того же элемента пользовательского интерфейса несколько раз. Это явление называется двойным налогообложением . Дополнительную информацию о двойном налогообложении и способах его предотвращения см. в разделе «Производительность и иерархии представлений» .

Используйте линтер

Рекомендуется запускать инструмент lint для проверки файлов разметки, чтобы найти возможные способы оптимизации иерархии представлений. Lint заменяет инструмент layoutopt и обладает расширенными функциями. Ниже приведены примеры правил lint:

  • Используйте составные графические элементы. Вы можете более эффективно обрабатывать LinearLayout , содержащий ImageView и TextView , используя составной графический элемент.
  • Объедините корневой фрейм. Если корнем макета является FrameLayout , который не предоставляет фон или отступы, вы можете заменить его тегом слияния, что немного эффективнее.
  • Удалите ненужные элементы. Вы можете удалить макет, у которого нет дочерних элементов или фона (поскольку он невидим), чтобы создать более плоскую и эффективную иерархию макета.
  • Удалите ненужные родительские элементы. Вы можете удалить макет с дочерним элементом, у которого нет соседей, который не является ScrollView или корневым макетом и не имеет фона. Вы также можете переместить дочерний элемент непосредственно в родительский для более плоской и эффективной иерархии макетов.
  • Избегайте глубокой компоновки. Компоновка со слишком большим количеством вложенных элементов плохо сказывается на производительности. Для повышения производительности рассмотрите возможность использования более плоских компоновок, таких как ConstraintLayout . Максимальная глубина проверки кода по умолчанию составляет 10.

Ещё одно преимущество инструмента Lint — его интеграция с Android Studio. Lint автоматически запускается при компиляции программы. В Android Studio вы также можете запускать проверку кода для конкретного варианта сборки или для всех вариантов сборки.

Вы также можете управлять профилями проверок и настраивать проверки в Android Studio с помощью пункта «Файл» > «Настройки» > «Настройки проекта» . Откроется страница «Конфигурация проверок» со списком поддерживаемых проверок:

Изображение, демонстрирующее меню проверок в Android Studio.
Рисунок 4. Страница настроек проверки.

Lint может автоматически исправлять одни ошибки, предлагать варианты для других и переходить непосредственно к проблемному коду для проверки.

Для получения более подробной информации см. раздел «Макеты и ресурсы по компоновке» .