Списки: LazyColumn и LazyRow

Строим длинные списки эффективно: LazyColumn рисует только видимые элементы, а ключи помогают Compose не путать строки.

LazyColumn — вертикальный список, который создаёт и держит в памяти только видимые на экране элементы.

Почему не Column для списков

Если положить тысячу элементов в обычный Column, Compose создаст их все сразу — даже те, что за пределами экрана. Это съест память и время. LazyColumn ленивый: он рисует только видимые элементы и подгружает следующие по мере прокрутки.

@Composable
fun NameList(names: List<String>) {
    LazyColumn {
        items(names) { name ->
            Text(text = name, modifier = Modifier.padding(8.dp))
        }
    }
}

Функция items(names) — это часть особого DSL внутри LazyColumn. Она перебирает коллекцию и для каждого элемента вызывает ваш блок. LazyRow устроен так же, но прокручивается горизонтально.

Зачем нужны ключи

При изменении списка (удалили элемент, поменяли порядок) Compose должен понять, какие строки остались прежними. По умолчанию он ориентируется на позицию, и это приводит к ошибкам: удалили первый элемент — и все состояния «съезжают». Ключ key привязывает строку к стабильному идентификатору:

LazyColumn {
    items(users, key = { user -> user.id }) { user ->
        UserRow(user)
    }
}

Теперь Compose отслеживает элемент по user.id, а не по позиции — состояния и анимации остаются у правильных строк.

Как работает под капотом

LazyColumn не строит весь список заранее. Он держит окно видимых элементов и небольшой буфер вокруг него. Когда вы прокручиваете, элементы, ушедшие за край, утилизируются (их слоты переиспользуются), а появляющиеся — создаются. Ключи помогают этому механизму корректно сопоставлять данные и переиспользуемые слоты при изменениях коллекции.

Частые ошибки

  • Использовать Column с прокруткой для большого списка — тормоза и перерасход памяти.
  • Не задавать key для изменяемых списков — состояние и анимации «перескакивают» на чужие строки.
  • Вкладывать LazyColumn в LazyColumn по одной оси — это вызывает ошибку бесконечной высоты; используйте один список с разными типами элементов.

Итог

  • LazyColumn/LazyRow создают только видимые элементы — это эффективно для длинных списков.
  • items(коллекция) { ... } перебирает данные внутри DSL списка.
  • key привязывает элемент к стабильному id и спасает состояние при изменениях.
Проверьте себя
1. Чем LazyColumn лучше обычного Column для длинных списков?
AОн красивее выглядит
BОн создаёт только видимые элементы, экономя память и время
CОн не требует состояния
DОн работает без модификаторов
2. Зачем задавать key в items?
AДля сортировки списка
BЧтобы Compose отслеживал элементы по стабильному id и не путал состояния при изменениях
CДля ускорения компиляции
DЭто обязательный параметр всегда
3. Какая функция перебирает коллекцию внутри LazyColumn?
AforEach
Bitems
Cmap
Drepeat