Списки: 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 и спасает состояние при изменениях.