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

В чем разница между процессами измерения у ViewGroup и Layout в Jetpack Compose?

1.7 Middle🔥 81 комментариев
#UI и вёрстка#Архитектура и паттерны

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

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

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

Разница между ViewGroup и Layout в Jetpack Compose

Эти два подхода к измерению и расположению элементов представляют два поколения Android UI-разработки. Хотя оба решают одну задачу, механизмы кардинально отличаются.

Измерение в классическом Android (ViewGroup)

ViewGroup — это контейнер, который содержит другие View и отвечает за их измерение и расположение.

Процесс измерения:

  1. Measure Pass — родитель передает constraints (ширина, высота)
  2. View вызывает setMeasuredDimension() для себя
  3. onMeasure() рекурсивно вызывает measure() для всех children
  4. Каждый child должен установить свой размер

Layout Pass — после измерения происходит расположение:

  1. onLayout() получает финальные размеры родителя
  2. Родитель вызывает layout() для каждого child
  3. Child получает свою позицию (left, top, right, bottom)

Код классического подхода:

class CustomViewGroup(context: Context) : ViewGroup(context) {
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        var totalHeight = 0
        var maxWidth = 0
        
        // Измеряем всех children
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            measureChild(child, widthMeasureSpec, heightMeasureSpec)
            totalHeight += child.measuredHeight
            maxWidth = maxOf(maxWidth, child.measuredWidth)
        }
        
        setMeasuredDimension(maxWidth, totalHeight)
    }
    
    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var y = 0
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            child.layout(0, y, child.measuredWidth, y + child.measuredHeight)
            y += child.measuredHeight
        }
    }
}

Измерение в Jetpack Compose (Layout)

Layout — это композиция, которая определяет, как расположить children.

Процесс измерения:

  1. Measure Pass — передаются constraints как Constraints объект
  2. Каждый composable вызывает layout() ламбду
  3. Layout-ламбда получает результаты измерения children
  4. Родитель сразу же расположит child (нет отдельного layout pass)

Ключевые отличия:

  • Single Pass Layout — вместо двух pass (measure + layout) одна
  • Декларативность — вместо imperative кода используются ламбды
  • Immutable — нет изменяемого состояния (в отличие от View)

Код Compose подхода:

@Composable
fun CustomLayout(content: @Composable () -> Unit) {
    Layout(content = content) { measurables, constraints ->
        val placeables = measurables.map { child ->
            child.measure(constraints)
        }
        
        var totalHeight = 0
        var maxWidth = 0
        
        placeables.forEach { placeable ->
            totalHeight += placeable.height
            maxWidth = maxOf(maxWidth, placeable.width)
        }
        
        layout(maxWidth, totalHeight) {
            var y = 0
            placeables.forEach { placeable ->
                placeable.place(0, y)
                y += placeable.height
            }
        }
    }
}

Сравнение

АспектViewGroupLayout (Compose)
PassДвухфазный (measure + layout)Однофазный
APIonMeasure(), onLayout()Layout() ламбда
StateИзменяемое (View переиспользуется)Immutable (переиспользуется функция)
PerformanceРекомпилкация при измененииRecomposition при изменении state
ДанныеMeasureSpec (int флаги)Constraints (специальный класс)
РасчетыВычисления в onLayout после measureРасчеты сразу в layout ламбде

Практическое значение

Compose имеет лучшую производительность благодаря:

  • Одному pass вместо двух
  • Лучшей типизации (Constraints вместо MeasureSpec)
  • Явной связи между measurement и placement
  • Отсутствием необходимости в переиспользовании View

Для начинающих: Compose скрывает сложность двухфазной системы ViewGroup, предоставляя более интуитивный и безопасный API.

В чем разница между процессами измерения у ViewGroup и Layout в Jetpack Compose? | PrepBro