Как использовать <merge> для оптимизации лейаутов?
2026-03-10 21:39 Diff

Теги: android, merge, android developer, android-программирование, android studio, layout

Представим себе простую ситуацию — нам нужно создать вью, отражающий название компании и её рейтинг, и его мы будем пятьдесят раз использовать в приложении. Например, что-то вроде:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <ImageView android:id="@+id/rating" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="16dp" /> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>

Теперь давайте создадим класс, его описывающий. Допустим, у нас будут два метода: один меняет картинку рейтинга в зависимости от значения, а другой задаёт имя:

public class RatingView extends LinearLayout { private TextView nameView; private ImageView ratingView; public RatingView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); LayoutInflater.from(context).inflate(R.layout.name_view, this); ratingView = findViewById(R.id.rating); nameView = findViewById(R.id.name); } public void setRating(int rating) { switch (rating) { case 1: ratingView.setImageResource(R.drawable.one_star); break; case 2: ratingView.setImageResource(R.drawable.two_star); break; case 3: ratingView.setImageResource(R.drawable.three_star); break; } } public void setName(String value) { nameView.setText(value); } }

Отлично. Теперь давайте запихнём наш вью в лейаут активити:

<android.support.constraint.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:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.otus.merge.RatingView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>

Запустим приложение и заглянем в Tools > Android > Layout Inspector — посмотрим, что же у нас там такое:

Вот как выглядит наше дерево вью:

Видим, что RatingView, расширяющий LinearLayout, содержит в себе ещё один LinearLayout, а внутри уже наши вьюшки. Теперь, используя <merge>, посмотрим, удастся ли нам исправить ситуацию:

<merge xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:parentTag="android.widget.LinearLayout" android:orientation="horizontal"> <ImageView android:id="@+id/rating" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="16dp" /> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </merge>

Запустили приложение. Идём в Tools > Android > Layout Inspector.

И, ура!

Мы убрали лишний LinearLayout.

Делаем выводы

Итак, для чего же был создан <merge>? Для оптимизации лейаутов путём уменьшения количества уровней в дереве вью. Когда LayoutInflater встречает этот тег, он пропускает его и добавляет дочерние элементы <merge> к родителю <merge>. Этот тег очень полезный и может использоваться во множестве ситуаций, а также он прекрасно комбинируется с <include>.

Несколько моментов, которые нужно учитывать: — <merge> всегда должен быть корневым тегом; — в <merge> нужно обязательно указывать parentTag, как мы сделали в примере выше.

Задать дополнительные вопросы по использованию <merge> всегда можно в комментариях.