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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође