LazyColumn — bu nima, Compose-da samarali ro'yxatlar

Muallif: IT Sectr Nashr etilgan: 2026-02-24 O'qish vaqti: 10 daq

LazyColumn — Jetpack Compose-ning kechiktirilgan yuklash bilan aylanma ro'yxatlarni ko'rsatish komponenti. RecyclerView-dan farqli o'laroq, LazyColumn ViewHolder yaratmaydi va XML ishlatmaydi — barcha elementlar composable-funksiyalar orqali deklarativ tarzda tavsiflanadi. LazyColumn nima ekanligini, LazyListState va items API qanday ishlashini va 60 FPS darajasida unumdorlikka qanday erishishni ko'rsatamiz. IT Sectr-da biz LazyColumn-dan barcha yangi Compose loyihalarida foydalanamiz. Klassik yondashuv bilan solishtirish uchun RecyclerView haqidagi maqolani o'qing.

Asosiy nuqtalar

  • LazyColumn — Material Design 3 ning bir qismi bo'lgan, kechiktirilgan yuklash bilan vertikal ro'yxatlar uchun Jetpack Compose komponenti.
  • LazyListState — ro'yxat holati: aylantirish pozitsiyasi, ko'rinadigan elementlar, dasturiy aylantirish.
  • items API — ma'lumotlarni bog'lash uchun kalitlarga ega items(), itemsIndexed(), items() funksiyalari.
  • key — elementlarning barqaror identifikatsiyasi uchun parametr, Compose-ga kompozitsiyani qayta ishlatishga imkon beradi.
  • LazyVerticalGrid — sobit sonli ustunlarga ega panjaralar uchun LazyColumn versiyasi.

Jetpack Compose-da LazyColumn nima?

LazyColumn — Foundation Compose kutubxonasidan olingan, kechiktirilgan (lazy) yuklash bilan vertikal elementlar ro'yxatini ko'rsatadigan composable-funksiya: faqat ekranda ko'rinadigan yoki yaqin atrofda joylashgan (prefetch zonasi) elementlar yaratiladi va kompozitsiya qilinadi. LazyColumn Compose 1.0 (2021) bilan birga LazyRow (gorizontal ro'yxat) va LazyVerticalGrid (panjara) bilan birga paydo bo'ldi.

Kechiktirilgan yuklash SubcomposeLayout mexanizmi orqali ishlaydi: LazyColumn mavjud joyni o'lchaydi, LayoutInfo-dan ko'rinadigan diapazonni so'raydi va faqat shu diapazondagi elementlarni kompozitsiya qiladi. Ekrandan chiqqan elementlar kompozitsiyani tark etadi (prefetch buferi bundan mustasno). Google ma'lumotlariga ko'ra (Android Performance, 2026), LazyColumn o'rta segment qurilmalarida 10000+ elementli ro'yxatni aylantirishda 60 FPS ni ta'minlaydi.

Column + ScrollState bilan farq

Column vertikal aylantirish bilan — verticalScroll modifierini qo'llash bilan barcha elementlarni bir-birining ostiga oddiy joylashtirish. Column dangasa emas: barcha bola elementlar ko'rinmasa ham darhol kompozitsiya qilinadi. 200+ elementli ro'yxat uchun Column boshlanishda sezilarli kechikishga sabab bo'ladi. LazyColumn faqat ko'rinadiganlarni + buferni (standart 1 ekran oldinga/ortga) kompozitsiya qiladi, bu uni uzoq ro'yxatlar uchun ajralmas qiladi.

items API: ma'lumotlarni ro'yxatga bog'lash

items API — LazyColumn uchun kengaytma funksiyalar to'plami, ma'lumotlar ro'yxatini va har bir element uchun DSL tavsifini qabul qiladi. Asosiy funksiyalar: sobit son uchun items(count, key, itemContent), ro'yxat uchun items(list, key, itemContent), indeks bilan itemsIndexed(list, key, itemContent). key parametri — unumdorlik uchun majburiy shart — Compose-ga elementning barqaror identifikatorini beradi.

kotlin
// itemContent bilan asosiy LazyColumn
@Composable
fun ArticleList(articles: List<Article>) {
    LazyColumn(
        modifier = Modifier.fillMaxSize(),
        contentPadding = PaddingValues(16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        // Header — dangasa emas, har doim boshida
        item {
            Text("Oxirgi maqolalar", style = MaterialTheme.typography.headlineMedium)
        }

        // Maqolalar ro'yxati id bilan kalit
        items(articles, key = { it.id }) { article ->
            ArticleCard(
                title = article.title,
                summary = article.summary,
                onClick = { onArticleClick(article.id) }
            )
        }

        // Yuklash ko'rsatkichi bilan Footer
        item {
            CircularProgressIndicator(
                modifier = Modifier.fillMaxWidth().padding(16.dp)
            )
        }
    }
}

// Maxsus ro'yxat elementi
@Composable
fun ArticleCard(title: String, summary: String, onClick: () -> Unit) {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = onClick)
    ) {
        Column(modifier = Modifier.padding(12.dp)) {
            Text(text = title, style = MaterialTheme.typography.titleMedium)
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = summary, style = MaterialTheme.typography.bodyMedium)
        }
    }
}

item {} vs items(): ro'yxatda doimo mavjud bo'lgan yagona elementlar (header, footer, ajratgichlar) uchun item {} ishlating. Dinamik ma'lumotlar ro'yxati uchun items() ishlating. items() Iterable yoki Int va har bir element uchun chaqiriladigan DSL blokini qabul qiladi. Bitta LazyColumn-da item va items-ni birlashtiring: chaqiruv tartibi ko'rsatish tartibini belgilaydi.

LazyListState: aylantirish pozitsiyasini boshqarish

LazyListState — ro'yxat holatini saqlaydigan obyekt: joriy aylantirish pozitsiyasi (firstVisibleItemIndex, firstVisibleItemScrollOffset), ko'rinadigan elementlar (layoutInfo) va dasturiy aylantirish usullari (scrollToItem, animateScrollToItem). LazyListState rememberLazyListState() orqali yaratiladi va state parametri orqali LazyColumn-ga uzatiladi.

kotlin
// Aylantirish pozitsiyasini saqlaydigan LazyColumn
@Composable
fun ScrollingList(items: List<Item>) {
    val listState = rememberLazyListState()

    Box(modifier = Modifier.fillMaxSize()) {
        LazyColumn(state = listState) {
            items(items, key = { it.id }) { item ->
                ListItemView(item = item)
            }
        }

        // "Yuqoriga" tugmasi 10-elementdan keyin paydo bo'ladi
        val showButton by remember {
            derivedStateOf { listState.firstVisibleItemIndex > 10 }
        }

        AnimatedVisibility(visible = showButton) {
            FloatingActionButton(
                modifier = Modifier
                    .align(Alignment.BottomEnd)
                    .padding(16.dp),
                onClick = {
                    coroutineScope.launch {
                        listState.animateScrollToItem(0)
                    }
                }
            ) {
                Icon(Icons.Default.KeyboardArrowUp, "Tepaga")
            }
        }
    }
}

// Ko'rinadigan elementlar haqida ma'lumot olish
@Composable
fun ListDebugInfo(listState: LazyListState) {
    val visibleItems = listState.layoutInfo.visibleItemsInfo
    val totalItems = listState.layoutInfo.totalItemsCount
    val firstItem = visibleItems.firstOrNull()?.index
    val lastItem = visibleItems.lastOrNull()?.index

    Text("$firstItem–$lastItem jami $totalItems dan ko'rsatilgan")
}

Dasturiy aylantirish listState-ning suspend-funksiyalari orqali bajariladi: scrollToItem(index, scrollOffset) — oniy harakat (animatsiyasiz), animateScrollToItem(index) — animatsiya bilan. Korutindan aylantirish uchun LaunchedEffect yoki coroutineScope.launch ishlating. Muhim: kompozitsiyadan (@Composable ichida) suspend-funksiyalarni chaqirmang — lambdalardan (onClick, LaunchedEffect) foydalaning.

LazyColumn vs RecyclerView: yondashuvlarni solishtirish

LazyColumn va RecyclerView bir xil vazifani hal qiladi — uzoq ro'yxatlarning samarali ko'rsatilishi. Farq arxitekturada: RecyclerView ViewHolder va Adapter (klassik Android View) ishlatadi, LazyColumn — XML va ViewHoldersiz deklarativ composable-funksiyalar. Tanlov loyihaning texnologiya stekiga bog'liq: Compose vs View-based UI.

ParametrLazyColumn (Compose)RecyclerView (View)
LayoutComposable-funksiyalar (Kotlin DSL)XML fayllari + ViewBinding
Adapteritems() / itemsIndexed() DSLRecyclerView.Adapter + ViewHolder
Saralash/filtratsiyaSnapshot state + derivedStateOfDiffUtil + AsyncListDiffer
AnimatsiyaAnimatedVisibility + Modifier.animateItemDefaultItemAnimator
Turli element turlariitem {}/items() + turga ko'ra whengetItemViewType + ko'p ViewHolder-lar
Pozitsiyaga aylantirishlistState.animateScrollToItem()layoutManager.scrollToPosition()
PrefetchIn-process (SubcomposeLayout buferi)RecycledViewPool + GapWorker
Tarmoq/paginatsiyacollectAsLazyPagingItems() + Paging 3PagingDataAdapter + Paging 3

Google tavsiyasi (Android Developers, 2026): Jetpack Compose-dagi yangi loyihalar uchun LazyColumn ishlating. View-based loyihalar uchun RecyclerView ishlating. LazyColumn Compose talab qiladi, bu APK-ga taxminan 3–5 MB qo'shadi — eski qurilmalarni qo'llab-quvvatlashda buni hisobga oling. Agar loyiha allaqachon View tizimidan foydalanayotgan bo'lsa, LazyColumn AndroidViewsiz XML layout bilan bir ekranda mavjud bo'la olmaydi — bunday hollarda RecyclerView-da qolish osonroq.

LazyVerticalGrid va LazyHorizontalGrid: panjaralar

LazyVerticalGrid — sobit sonli ustunlarga (columns) ega panjaralar uchun LazyColumn versiyasi. LazyHorizontalGrid — sobit sonli qatorlarga (rows) ega gorizontal panjara. Ikkala komponent LazyColumn bilan bir xil kechiktirilgan yuklash tamoyillaridan va bir xil items API-dan foydalanadi. columns parametri GridCells.Fixed(N) yoki GridCells.Adaptive(minSize) orqali ustunlar sonini belgilaydi.

kotlin
// Adaptiv ustunlar bilan panjara
@Composable
fun PhotoGrid(photos: List<Photo>) {
    LazyVerticalGrid(
        columns = GridCells.Adaptive(minSize = 128.dp),
        contentPadding = PaddingValues(8.dp),
        horizontalArrangement = Arrangement.spacedBy(8.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        items(photos, key = { it.id }) { photo ->
            AsyncImage(
                model = photo.url,
                contentDescription = photo.title,
                modifier = Modifier.aspectRatio(1f)
            )
        }
    }
}

// Gorizontal ro'yxat (LazyRow)
@Composable
fun CategoryCarousel(categories: List<Category>) {
    LazyRow(
        contentPadding = PaddingValues(horizontal = 16.dp),
        horizontalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        items(categories, key = { it.id }) { category ->
            FilterChip(
                selected = category.isSelected,
                onClick = { onCategoryClick(category.id) },
                label = { Text(category.name) }
            )
        }
    }
}

GridCells.Adaptive hujayraning minimal o'lchamiga asoslanib ustunlar sonini avtomatik hisoblaydi. Masalan, GridCells.Adaptive(128.dp) 360 dp kenglikdagi ekranda 2 ustunni, 600 dp planshetda 4 ustunni joylashtiradi. GridCells.Fixed(2) har doim aniq 2 ustunni ko'rsatadi. Adaptive ko'p ekranli moslashuv uchun afzal — media so'rovlarsiz ekran kengligiga avtomatik moslashadi.

LazyColumn unumdorligi: key, contentType, prefetch

Unumdorlik LazyColumn uch omilga bog'liq: kalitlarning barqarorligi (key), kontent turi (contentType) va prefetch buferi (beyondBounds). Standartda LazyColumn 1 ekran oldinga va 1 orqaga buferlaydi. Google (Android Developers, 2026) ushbu parametrlarni turli element turlari yoki murakkab kompozitsiyaga ega ro'yxatlar uchun sozlashni tavsiya qiladi.

ParametrTavsifTavsiya
keyElementning barqaror identifikatoriHar doim key = { it.id } ni belgilang. Keysiz Compose indeksdan foydalanadi va elementlarni qayta tartiblash animatsiyani buzadi.
contentTypeHovuzlarni ajratish uchun kontent turiTurli element turlari (matn + rasm + reklama) bo'lgan ro'yxatlar uchun belgilang. Compose faqat bitta contentType ichida kompozitsiyani qayta ishlatadi.
beyondBoundsPrefetch uchun ekranlar soniOg'ir rasmlari bo'lgan ro'yxatlar uchun 2–3 gacha oshiring. Standart 1 ekran.
Modifier.animateItemPozitsiya o'zgarishi animatsiyasiAnimatsiyali saralash va filtratsiya uchun ishlating (Compose 1.7+).
kotlin
// contentType va prefetch bilan optimallashtirilgan LazyColumn
@Composable
fun OptimizedFeed(items: List<FeedItem>) {
    val listState = rememberLazyListState()

    LazyColumn(
        state = listState,
        modifier = Modifier.fillMaxSize(),
        beyondBoundsPageCount = 2  // prefetch 2 ekran
    ) {
        items(
            items = items,
            key = { it.id },
            contentType = { it.type }  // turlarga ko'ra bo'lish
        ) { item ->
            when (item) {
                is FeedItem.Post -> PostView(item)
                is FeedItem.Ad -> AdView(item)
                is FeedItem.Suggested -> SuggestedView(item)
            }
        }
    }
}

// listState orqali unumdorlikni o'lchash
@Composable
fun ScrollPerformance(listState: LazyListState) {
    val scrollInfo = listState.layoutInfo
    val visibleCount = scrollInfo.visibleItemsInfo.size
    val total = scrollInfo.totalItemsCount

    // derivedStateOf — qiymat o'zgarmasa qayta tuzilmaydi
    val scrollProgress by remember {
        derivedStateOf {
            if (total > 0) visibleCount.toFloat() / total else 0f
        }
    }

    LinearProgressIndicator(
        progress = scrollProgress,
        modifier = Modifier.fillMaxWidth().height(2.dp)
    )
}

Keng tarqalgan xatolar: (1) key yo'qligi — elementlar ro'yxat har o'zgarishida qayta kompozitsiya qilinadi; (2) snapshot oqimlarisiz mutableStateListOf ishlatish — o'zgarishlar kuzatilmasligi mumkin; (3) itemContent ichida suspend-funksiyalarni chaqirish — kompozitsiyani to'xtatadi; (4) aralash turlar uchun contentType yo'qligi — Compose matn posti uchun reklama kompozitsiyasini qayta ishlatadi, vizual artefaktlarga sabab bo'ladi. IT Sectr-da biz uch va undan ortiq kontent turiga ega barcha ro'yxatlarga contentType qo'shamiz.

Tez-tez beriladigan savollar

LazyColumn sekin aylanadi — nima qilish kerak?

Uch parametrni tekshiring: (1) key — barqaror kalitsiz Compose kompozitsiyani qayta ishlata olmaydi, (2) contentType — turli element turlari bo'lgan ro'yxatlar uchun, (3) beyondBoundsPageCount — rasmlar uchun 2 gacha oshiring. itemContent ichidagi og'ir hisoblashlarni ma'lumot kaliti bilan remember-ga ko'chiring. Oddiy grafika uchun Image o'rniga Modifier.drawWithContent ishlating.

LazyColumn elementlari orasiga ajratgichni qanday qo'shish mumkin?

Elementlar orasidagi bo'shliqlar uchun LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) ishlating. Chiziqli vizual ajratgich uchun items orasiga item { Divider() } qo'shing. Avtomatik ajratgich: items(items, key = { it.id }) { item -> ... }, va har bir element orasiga item { HorizontalDivider() } kiriting. Buning uchun LazyListScope.items(list, key) { /* element */ } va alohida LazyListScope.item { Divider() } ishlating.

LazyColumn Column ichida ishlamaydi — nega?

LazyColumn standartda cheksiz balandlikka (fillMaxSize) ega. Balandligi sobit bo'lmagan Column ichida LazyColumn o'lchamni aniqlay olmaydi. Yechim: (1) LazyColumn-ga sobit balandlik bering: Modifier.height(400.dp), (2) Column ichida Modifier.weight(1f) ishlating, (3) LazyColumn-ni vertikal aylanadigan konteynerga joylashtirmang — LazyColumn-ni header va footer uchun item {} bilan ildiz element sifatida ishlating.

Ma'lumot o'zgarganda LazyColumn-ni qanday yangilash mumkin?

LazyColumn State o'zgarishlariga avtomatik munosabat bildiradi. Agar ma'lumot mutableStateListOf yoki mutableStateOf da saqlansa, Compose faqat o'zgargan elementlarni qayta kompozitsiya qiladi. ViewModel-dan ro'yxatlar uchun Flow bilan collectAsState() ishlating. Key bilan ro'yxat yangilanganda, Compose o'zgarishlarni (qo'shish, o'chirish, ko'chirish) Modifier.animateItemPlacement() orqali avtomatik animatsiya qiladi.

LazyColumn vs LazyVerticalGrid — nimani tanlash kerak?

LazyColumn — bir ustunli ro'yxatlar uchun (lenta, chat, sharhlar). LazyVerticalGrid — panjaralar uchun (galereya, katalog, ikonkalar). Agar elementlar telefonda bir ustunda, planshetda esa ikki ustunda bo'lishi kerak bo'lsa — GridCells.Adaptive bilan LazyVerticalGrid ishlating. Agar aralash panjara (bir bo'limda turli xil ustunlar soni) kerak bo'lsa — LazyColumn ishlating va items ichida gorizontal LazyRow yoki ichma-ich LazyVerticalGrid joylashtiring.

Xulosa

  • LazyColumn — deklarativ API bilan dangasa vertikal ro'yxatlar uchun Jetpack Compose komponenti.
  • items() API ro'yxat va har bir element uchun DSL blokini qabul qiladi; key unumdorlik uchun majburiy.
  • LazyListState aylantirish pozitsiyasini boshqaradi, dasturiy aylantirish uchun suspend-funksiyalar taqdim etadi.
  • contentType turli element turlari bo'lgan ro'yxatlar uchun kompozitsiya hovuzlarini ajratadi.
  • LazyVerticalGrid / LazyRow — bir xil items API bilan panjaralar va gorizontal ro'yxatlar uchun variantlar.
  • LazyColumn SubcomposeLayout va prefetch buferi tufayli 10000+ element uchun 60 FPS ni ta'minlaydi.
  • Yangi Compose loyihalari uchun LazyColumn ishlating; View-based loyihalar uchun — RecyclerView.

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing