LazyColumn — це composable-функція в Jetpack Compose для створення вертикальних списків із лінивим завантаженням елементів. На відміну від Column, LazyColumn створює та компонує лише видимі на екрані елементи, перевикористовуючи їх під час прокручування. За даними Google Android Documentation, 2025, LazyColumn є основним інструментом для відображення великих наборів даних у мобільних додатках завдяки ефективному управлінню пам’яттю.
Основне
LazyColumn — це composable-функція, яка реалізує вертикальний прокручуваний список із лінивим завантаженням. На відміну від Column, який відображає всі дочірні елементи одразу, LazyColumn створює лише елементи, що потрапляють в область перегляду.
Механізм лінивого завантаження в LazyColumn заснований на перевикористанні елементів: коли елемент приховується під час прокручування, його композиція та макет можуть бути перевикористані для нового відображуваного елемента. Це економить пам’ять і процесорний час, особливо на довгих списках.
За даними Android Developers Blog, 2024, LazyColumn може ефективно обробляти списки з десятків тисяч елементів без значного зниження продуктивності. Кожен елемент у LazyColumn має ключ (key), який допомагає Compose ідентифікувати та зберігати стан елемента при змінах списку.
LazyColumn приймає параметри modifier, state, contentPadding, reverseLayout, verticalArrangement та horizontalAlignment. Вміст задається в лямбда-блоці через DSL-функції items та item.
@Composable
fun SimpleLazyColumn() {
val itemsList = (1..100).toList()
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(16.dp)
) {
items(itemsList) { item ->
Text(text = "Елемент $item")
}
}
}
DSL-блок LazyColumn надає функції items та item для додавання вмісту. items приймає колекцію даних, ключ та функцію-фабрику для створення елементів. item додає один статичний елемент до списку.
itemsIndexed — це варіант items, який передає індекс елемента на додаток до даних. Це корисно, коли потрібно знати позицію елемента без окремого обчислення. items(size) приймає лише кількість елементів та фабрику без прив’язки до колекції.
Параметр key у items унікально ідентифікує кожен елемент. За даними Material Design Guidelines, 2025, ключі покращують продуктивність при оновленні та анімації елементів, оскільки Compose може відстежити переміщення або зміну конкретного елемента за ключем.
Функція items з contentType дозволяє LazyColumn оптимізувати перевикористання елементів різних типів. У прикладі нижче в одному списку використовуються заголовки секцій та звичайні рядки.
@Composable
fun MixedItemsList() {
LazyColumn {
item {
Text(
text = "Заголовок",
style = MaterialTheme.typography.headlineMedium
)
}
items(
items = (1..20).toList(),
key = { it },
contentType = { "item" }
) { item ->
Text(text = "Рядок $item")
}
}
}
LazyListState — це об’єкт стану LazyColumn, який відстежує поточну позицію прокручування, перший видимий елемент та зміщення. Він може бути створений через rememberLazyListState() та переданий у параметр state LazyColumn.
LazyListState надає методи animateScrollToItem та scrollToItem для програмного прокручування до певного елемента. animateScrollToItem створює плавну анімацію прокручування, а scrollToItem прокручує миттєво. Обидва методи вимагають виклику всередині корутини в CompositionContext.
За даними Android Developers, 2024, LazyListState також містить layoutInfo, який надає інформацію про видимі елементи — їх індекси, зміщення та розміри. Це корисно для реалізації аналітики, відстеження переглядів або нескінченного прокручування.
У цьому прикладі LazyColumn керується через LazyListState. Кнопка прокручує список до елемента з індексом 50 з плавною анімацією.
@Composable
fun ScrollableList() {
val listState = rememberLazyListState()
val scope = rememberCoroutineScope()
Column {
Button(
onClick = {
scope.launch {
listState.animateScrollToItem(50)
}
}
) {
Text("Прокрутити до 50")
}
LazyColumn(state = listState) {
items((1..100).toList()) { item ->
Text(
text = "Елемент $item",
modifier = Modifier.padding(8.dp)
)
}
}
}
}
Ключовий фактор продуктивності LazyColumn — правильне використання ключів. Кожен елемент повинен мати унікальний стабільний ключ через параметр key. Без ключів Compose не може коректно перевикористовувати елементи при зміні даних, що призводить до перекомпонування.
contentType повідомляє LazyColumn, які елементи мають однаковий тип макету. Коли два елементи з однаковим contentType потрапляють в область переробки, LazyColumn може перевикористовувати їх макет без перекомпонування. За даними Android Developers Blog, 2024, contentType покращує продуктивність на 30–50% у списках з різними типами елементів.
Для LazyColumn також важливо уникати нестабільних параметрів у функціях-фабриках. Щоразу, коли параметр елемента змінюється, Compose перекомпоновує цей елемент. Використання remember та derivedStateOf для стабільних значень знижує кількість перекомпонувань.
| Фактор | Вплив | Рекомендація |
|---|---|---|
| Ключі (key) | Критичний | Завжди задавайте унікальний стабільний key для items |
| contentType | Значний | Вказуйте тип елемента для оптимізації перевикористання |
| Розмір елементів | Середній | Використовуйте фіксовані розміри де можливо |
| Вкладені списки | Критичний | Уникайте LazyColumn всередині LazyColumn — використовуйте LazyVerticalGrid |
stickyHeader — це функція DSL LazyColumn, яка закріплює заголовок секції у верхній частині списку під час прокручування. Коли наступна секція доходить до верху, її заголовок замінює поточний. Ця поведінка знайома користувачам за списками контактів та календарями.
stickyHeader приймає ключ та функцію-фабрику, аналогічно item. На відміну від звичайного item, stickyHeader залишається видимим під час прокручування вмісту своєї секції. Коли секція повністю прокручена, заголовок наступної секції витісняє попередній.
За даними Material Design Guidelines, 2025, sticky header покращує навігацію в довгих списках та знижує когнітивне навантаження на користувача. Для реалізації sticky header достатньо обернути заголовок секції в stickyHeader у правильній позиції відносно елементів items.
@Composable
fun SectionedList(sections: Map<String, List<String>>) {
LazyColumn {
sections.forEach { (header, items) ->
stickyHeader {
Text(
text = header,
modifier = Modifier.background(Color.White)
.padding(16.dp)
)
}
items(items) { item ->
Text(text = item, modifier = Modifier.padding(8.dp))
}
}
}
}
Часті запитання
Column відображає всі елементи одразу та підходить для списків до 20–30 елементів. LazyColumn створює лише видимі елементи та перевикористовує їх під час прокручування, що дозволяє працювати з тисячами елементів без втрати продуктивності.
Використовуйте Arrangement.spacedBy у параметрі verticalArrangement або функціями items з роздільником через індекс. Для складних роздільників додайте окремий item з Divider() між елементами списку.
LazyColumn автоматично перекомпоновується при зміні колекції даних, якщо використовуються стабільні ключі. Зміни в даних, виявлені через mutableStateListOf або StateFlow, призводять до перемальовування лише змінених елементів.
Пряма вкладеність LazyColumn у LazyColumn не рекомендується — обидві мають незалежне прокручування, що створює конфлікт жестів. Натомість використовуйте звичайний Column з LazyColumn всередині прокручуваної Section або LazyVerticalGrid для сіток.
Використовуйте LazyListState.layoutInfo.visibleItemsInfo та порівняйте індекс останнього видимого елемента із загальною кількістю елементів. Для нескінченного прокручування відстежуйте, коли останній видимий елемент наближається до кінця списку.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також