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

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

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

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

Проверьте свой макет

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

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

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

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

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

Изображение, показывающее Layout Inspector и композицию 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. 3D-режим Layout Inspector.

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

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

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

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

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

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

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

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

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

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

Дополнительные сведения см. в разделе Макеты и ресурс макета .