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 вътре в превъртаща се секция или LazyVerticalGrid за мрежи.
Използвайте LazyListState.layoutInfo.visibleItemsInfo и сравнете индекса на последния видим елемент с общия брой елементи. За безкрайно превъртане проследявайте кога последният видим елемент се приближава до края на списъка.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също