← Назад к вопросам

Сколько раз может происходить измерение дочерних View во ViewGroup?

1.7 Middle🔥 182 комментариев
#UI и вёрстка#Производительность и оптимизация

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Динамика измерения дочерних View во ViewGroup

Количество измерений дочерних View внутри ViewGroup — один из ключевых аспектов производительности UI в Android. В идеальном случае каждая дочерняя View измеряется ровно один раз за проход layout-процесса. Однако на практике измерения могут происходить многократно из-за сложности иерархии View, особенностей контейнеров (например, wrap_content, весов в LinearLayout) и специфичных требований родительского контейнера.

Основные причины многократных измерений

  1. ViewGroup.onMeasure() может вызывать measure() для дочерних View несколько раз, особенно если:

    • Размеры родителя или дочерних View зависят друг от друга (например, RelativeLayout).
    • Используются веса (layout_weight) в LinearLayout, которые требуют двух проходов измерения.
    • Реализация ViewGroup (например, кастомная) требует пробных замеров для определения оптимальной компоновки.
  2. Вложенные wrap_content и match_parent создают рекурсивную зависимость. Например:

    <!-- LinearLayout с wrap_content внутри другого wrap_content -->
    <LinearLayout android:layout_width="wrap_content">
        <LinearLayout android:layout_width="wrap_content">
            <TextView android:layout_width="wrap_content"/>
        </LinearLayout>
    </LinearLayout>
    

    Здесь внутренний TextView может измеряться несколько раз, пока внешние контейнеры определяют свои размеры.

  3. RelativeLayout известен тем, что вызывает двойное измерение дочерних View из-за необходимости учета сложных зависимостей (выравнивания, относительные позиции). Это поведение оптимизировано в новых версиях, но всё ещё актуально для глубоких иерархий.

  4. Изменение размера или состояния View (например, изменение текста, видимости) приводит к повторным измерениям через requestLayout().

  5. Анимации и переходы, изменяющие размеры View, также инициируют перемеры.

Пример с LinearLayout и весами

При использовании layout_weight в LinearLayout происходит два прохода измерения:

  • Первый проход: измерение дочерних View без учёта весов.
  • Второй проход: перераспределение оставшегося пространства между View с весами.
// Упрощённая логика измерения в LinearLayout с весами
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // Первый проход: измеряем все дочерние View
    measureChildren(widthMeasureSpec, heightMeasureSpec);
    
    // Второй проход: перемеряем View с weight
    for (View child : getChildren()) {
        if (child.getLayoutParams().weight > 0) {
            // Измеряем заново с учётом доступного пространства
            measureChildWithMargins(child, ...);
        }
    }
}

Как избежать лишних измерений?

  • Минимизируйте вложенность View — используйте ConstraintLayout вместо цепочек LinearLayout/RelativeLayout.
  • Избегайте wrap_content и match_parent в глубоких иерархиях — по возможности задавайте фиксированные размеры или 0dp в ConstraintLayout.
  • Кэшируйте размеры в кастомных View через onMeasure():
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        if (isSizeCached) {
            setMeasuredDimension(cachedWidth, cachedHeight)
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
            cachedWidth = measuredWidth
            cachedHeight = measuredHeight
            isSizeCached = true
        }
    }
    
  • Используйте инструменты профилирования в Android Studio (Layout Inspector, GPU Rendering) для выявления лишних проходов.

Вывод

В реальных приложениях дочерние View могут измеряться от одного до десятков раз в зависимости от сложности layout, использования весов, анимаций и динамических изменений. Критически важно оптимизировать иерархию View для минимизации избыточных измерений, так как они напрямую влияют на частоту кадров и отзывчивость интерфейса.

Сколько раз может происходить измерение дочерних View во ViewGroup? | PrepBro