LazyColumn — یہ کیا ہے، Compose میں موثر فہرستیں

مصنف: IT Sectr اشاعت: 2026-02-24 مطالعے کا وقت: 10 منٹ

LazyColumn — Jetpack Compose کا ایک جزو جو سست لوڈنگ کے ساتھ اسکرول قابل فہرستیں دکھاتا ہے۔ RecyclerView کے برعکس، LazyColumn ViewHolders نہیں بناتا اور XML استعمال نہیں کرتا — تمام عناصر composable فنکشنز کے ذریعے اعلانیہ طور پر بیان کیے جاتے ہیں۔ ہم دکھاتے ہیں کہ LazyColumn کیا ہے، LazyListState اور items API کیسے کام کرتے ہیں، اور 60 FPS کارکردگی کیسے حاصل کی جائے۔ IT Sectr میں ہم تمام نئے Compose پروجیکٹس میں LazyColumn استعمال کرتے ہیں۔ کلاسک طریقہ سے موازنہ کے لیے، RecyclerView کے بارے میں مضمون پڑھیں۔

اہم نکات

  • LazyColumn — سست لوڈنگ کے ساتھ عمودی فہرستوں کے لیے Jetpack Compose کا ایک جزو، Material Design 3 کا حصہ۔
  • LazyListState — فہرست کی حالت: اسکرول پوزیشن، دکھائی دینے والے عناصر، پروگراماتی اسکرولنگ۔
  • items API — ڈیٹا بائنڈنگ کے لیے کنجیوں کے ساتھ items()، itemsIndexed()، items() فنکشنز۔
  • key — عناصر کی مستحکم شناخت کے لیے پیرامیٹر، Compose کو ترکیب دوبارہ استعمال کرنے کی اجازت دیتا ہے۔
  • LazyVerticalGrid — مقررہ کالم والے گرڈ کے لیے LazyColumn کا ورژن۔

Jetpack Compose میں LazyColumn کیا ہے؟

LazyColumn Foundation Compose لائبریری کا ایک composable فنکشن ہے جو سست لوڈنگ کے ساتھ عناصر کی عمودی فہرست دکھاتا ہے: صرف اسکرین پر دکھائی دینے والے یا قریبی عناصر (prefetch زون) بنائے اور مرتب کیے جاتے ہیں۔ LazyColumn Compose 1.0 (2021) میں LazyRow (افقی فہرست) اور LazyVerticalGrid (گرڈ) کے ساتھ ظاہر ہوا۔

سست لوڈنگ SubcomposeLayout میکانزم کے ذریعے کام کرتی ہے: LazyColumn دستیاب جگہ کی پیمائش کرتا ہے، LayoutInfo سے دکھائی دینے والی رینج کی درخواست کرتا ہے، اور صرف اس رینج میں عناصر کو مرتب کرتا ہے۔ اسکرین سے باہر جانے والے عناصر ترکیب چھوڑ دیتے ہیں (prefetch بفر کے علاوہ)۔ Google (Android Performance، 2026) کے مطابق، LazyColumn درمیانی درجے کے آلات پر 10000+ عناصر کی فہرست میں اسکرول کرتے ہوئے 60 FPS برقرار رکھتا ہے۔

Column + ScrollState سے فرق

Column عمودی اسکرول کے ساتھ — verticalScroll موڈیفائر کے ساتھ تمام عناصر کی ایک دوسرے کے نیچے عام ترتیب ہے۔ Column سست نہیں ہے: تمام ذیلی عناصر فوری طور پر مرتب کیے جاتے ہیں، چاہے وہ دکھائی نہ دیں۔ 200+ عناصر کی فہرست کے لیے، Column شروع ہونے میں نمایاں تاخیر کا سبب بنتا ہے۔ LazyColumn صرف دکھائی دینے والے عناصر + بفر (بطور ڈیفالٹ 1 اسکرین آگے/پیچھے) مرتب کرتا ہے، جو اسے لمبی فہرستوں کے لیے ناگزیر بناتا ہے۔

items API: فہرست میں ڈیٹا بائنڈنگ

items API LazyColumn کے لیے توسیعی فنکشنز کا ایک سیٹ ہے جو ڈیٹا کی فہرست اور ہر عنصر کے لیے DSL وضاحت کنندہ قبول کرتا ہے۔ اہم فنکشنز یہ ہیں: مقررہ تعداد کے لیے items(count, key, itemContent)، فہرست کے لیے items(list, key, itemContent)، انڈیکس کے ساتھ itemsIndexed(list, key, itemContent)۔ key پیرامیٹر کارکردگی کے لیے لازمی ہے — یہ Compose کو ایک مستحکم عنصر شناخت کنندہ دیتا ہے۔

kotlin
// itemContent کے ساتھ بنیادی LazyColumn
@Composable
fun ArticleList(articles: List<Article>) {
    LazyColumn(
        modifier = Modifier.fillMaxSize(),
        contentPadding = PaddingValues(16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        // Header — سست نہیں، ہمیشہ شروع میں
        item {
            Text("تازہ ترین مضامین", style = MaterialTheme.typography.headlineMedium)
        }

        // id کے مطابق کلید کے ساتھ مضامین کی فہرست
        items(articles, key = { it.id }) { article ->
            ArticleCard(
                title = article.title,
                summary = article.summary,
                onClick = { onArticleClick(article.id) }
            )
        }

        // لوڈنگ انڈیکیٹر کے ساتھ Footer
        item {
            CircularProgressIndicator(
                modifier = Modifier.fillMaxWidth().padding(16.dp)
            )
        }
    }
}

// اپنی مرضی کا فہرست عنصر
@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 {} بمقابلہ items(): واحد عناصر کے لیے item {} استعمال کریں جو فہرست میں ہمیشہ موجود ہوتے ہیں (ہیڈر، فوٹر، جدا کرنے والے)۔ متحرک ڈیٹا فہرست کے لیے items() استعمال کریں۔ items() ایک Iterable یا Int اور ایک DSL بلاک قبول کرتا ہے جو ہر عنصر کے لیے بلایا جاتا ہے۔ ایک LazyColumn میں item اور items کو یکجا کریں: کالوں کی ترتیب ڈسپلے ترتیب کا تعین کرتی ہے۔

LazyListState: اسکرول پوزیشن کا انتظام

LazyListState ایک آبجیکٹ ہے جو فہرست کی حالت ذخیرہ کرتا ہے: موجودہ اسکرول پوزیشن (firstVisibleItemIndex، firstVisibleItemScrollOffset)، دکھائی دینے والے عناصر (layoutInfo)، اور پروگراماتی اسکرولنگ کے طریقے (scrollToItem، animateScrollToItem)۔ LazyListState rememberLazyListState() کے ذریعے بنایا جاتا ہے اور state پیرامیٹر کے ذریعے LazyColumn کو بھیجا جاتا ہے۔

kotlin
// اسکرول پوزیشن برقرار رکھنے والا 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)
            }
        }

        // "اوپر" بٹن 10ویں عنصر کے بعد ظاہر ہوتا ہے
        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, "اوپر جائیں")
            }
        }
    }
}

// دکھائی دینے والے عناصر کی معلومات حاصل کرنا
@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("$totalItems میں سے $firstItem–$lastItem دکھا رہا ہے")
}

پروگراماتی اسکرولنگ listState کے suspend فنکشنز کے ذریعے کی جاتی ہے: scrollToItem(index, scrollOffset) — فوری حرکت (بغیر اینیمیشن)، animateScrollToItem(index) — اینیمیشن کے ساتھ۔ coroutine سے اسکرول کرنے کے لیے، LaunchedEffect یا coroutineScope.launch استعمال کریں۔ اہم: ترکیب کے اندر (@Composable کے اندر) suspend فنکشنز کو کال نہ کریں — لیمبڈا (onClick، LaunchedEffect) استعمال کریں۔

LazyColumn بمقابلہ RecyclerView: طریقوں کا موازنہ

LazyColumn اور RecyclerView ایک ہی مسئلہ حل کرتے ہیں — لمبی فہرستوں کی موثر ڈسپلے۔ فرق فن تعمیر میں ہے: RecyclerView ViewHolder اور Adapter (کلاسک Android View) استعمال کرتا ہے، LazyColumn XML یا ViewHolder کے بغیر اعلانیہ composable فنکشنز استعمال کرتا ہے۔ انتخاب پروجیکٹ کے ٹیکنالوجی اسٹیک پر منحصر ہے: Compose بمقابلہ View پر مبنی UI۔

پیرامیٹرLazyColumn (Compose)RecyclerView (View)
لی آؤٹComposable فنکشنز (Kotlin DSL)XML فائلز + ViewBinding
اڈاپٹرitems() / itemsIndexed() DSLRecyclerView.Adapter + ViewHolder
ترتیب/فلٹرنگSnapshot state + derivedStateOfDiffUtil + AsyncListDiffer
اینیمیشنAnimatedVisibility + Modifier.animateItemDefaultItemAnimator
مختلف عناصر کی اقسامitem {}/items() + قسم کے مطابق whengetItemViewType + متعدد ViewHolders
پوزیشن پر اسکرولlistState.animateScrollToItem()layoutManager.scrollToPosition()
Prefetchان پروسیس (SubcomposeLayout بفر)RecycledViewPool + GapWorker
نیٹ ورک/صفحہ بندیcollectAsLazyPagingItems() + Paging 3PagingDataAdapter + Paging 3

Google کی تجویز (Android Developers، 2026): Jetpack Compose پر نئے پروجیکٹس کے لیے LazyColumn استعمال کریں۔ View پر مبنی پروجیکٹس کے لیے RecyclerView استعمال کریں۔ LazyColumn کو Compose کی ضرورت ہے، جو APK میں تقریباً 3–5 MB کا اضافہ کرتا ہے — پرانے آلات کی حمایت کرتے وقت اس پر غور کریں۔ اگر کوئی پروجیکٹ پہلے سے View سسٹم استعمال کرتا ہے، تو LazyColumn AndroidView کے بغیر ایک اسکرین میں XML لی آؤٹ کے ساتھ共存 نہیں کر سکتا — ایسی صورتوں میں، RecyclerView کے ساتھ رہنا آسان ہے۔

LazyVerticalGrid اور LazyHorizontalGrid: گرڈ

LazyVerticalGrid مقررہ کالم والے گرڈ کے لیے LazyColumn کا ایک ورژن ہے۔ LazyHorizontalGrid مقررہ قطاروں والا ایک افقی گرڈ ہے۔ دونوں اجزاء LazyColumn جیسے ہی سست لوڈنگ کے اصول اور ایک ہی items API استعمال کرتے ہیں۔ columns پیرامیٹر GridCells.Fixed(N) یا GridCells.Adaptive(minSize) کے ذریعے کالموں کی تعداد کا تعین کرتا ہے۔

kotlin
// مطابقت پذیر کالموں والا گرڈ
@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)
            )
        }
    }
}

// افقی فہرست (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 کم سے کم سیل سائز کی بنیاد پر خود بخود کالموں کی تعداد کا حساب لگاتا ہے۔ مثال کے طور پر، GridCells.Adaptive(128.dp) 360 dp چوڑی اسکرین پر 2 کالم رکھتا ہے، 600 dp ٹیبلیٹ پر — 4 کالم۔ GridCells.Fixed(2) ہمیشہ بالکل 2 کالم دکھاتا ہے۔ Adaptive ملٹی اسکرین موافقت کے لیے ترجیح دی جاتی ہے — یہ میڈیا کوریز کے بغیر خود بخود اسکرین کی چوڑائی میں ایڈجسٹ ہو جاتا ہے۔

LazyColumn کی کارکردگی: key، contentType، prefetch

LazyColumn کی کارکردگی تین عوامل پر منحصر ہے: کلید استحکام (key)، مواد کی قسم (contentType)، اور prefetch بفر (beyondBounds)۔ بطور ڈیفالٹ، LazyColumn 1 اسکرین آگے اور 1 پیچھے بفر کرتا ہے۔ Google (Android Developers، 2026) مختلف عناصر کی اقسام یا پیچیدہ ترکیب والی فہرستوں کے لیے ان پیرامیٹرز کو ترتیب دینے کی تجویز کرتا ہے۔

پیرامیٹروضاحتتجویز
keyمستحکم عنصر شناخت کنندہہمیشہ key = { it.id } بتائیں۔ کلید کے بغیر، Compose انڈیکس استعمال کرتا ہے اور عناصر کی دوبارہ ترتیب اینیمیشن کو توڑ دیتی ہے۔
contentTypeپول علیحدگی کے لیے مواد کی قسممختلف عناصر کی اقسام (متن + تصویر + اشتہار) والی فہرستوں کے لیے بتائیں۔ Compose صرف اسی contentType کے اندر ترکیب دوبارہ استعمال کرے گا۔
beyondBoundsprefetch اسکرینوں کی تعدادبھاری تصاویر والی فہرستوں کے لیے 2–3 تک بڑھائیں۔ ڈیفالٹ 1 اسکرین ہے۔
Modifier.animateItemپوزیشن تبدیلی اینیمیشناینیمیٹڈ ترتیب اور فلٹرنگ کے لیے استعمال کریں (Compose 1.7+)۔
kotlin
// contentType اور prefetch کے ساتھ بهینہ ترین LazyColumn
@Composable
fun OptimizedFeed(items: List<FeedItem>) {
    val listState = rememberLazyListState()

    LazyColumn(
        state = listState,
        modifier = Modifier.fillMaxSize(),
        beyondBoundsPageCount = 2  // 2 اسکرینوں کا prefetch
    ) {
        items(
            items = items,
            key = { it.id },
            contentType = { it.type }  // قسم کے مطابق تقسیم
        ) { item ->
            when (item) {
                is FeedItem.Post -> PostView(item)
                is FeedItem.Ad -> AdView(item)
                is FeedItem.Suggested -> SuggestedView(item)
            }
        }
    }
}

// listState کے ذریعے کارکردگی کی پیمائش
@Composable
fun ScrollPerformance(listState: LazyListState) {
    val scrollInfo = listState.layoutInfo
    val visibleCount = scrollInfo.visibleItemsInfo.size
    val total = scrollInfo.totalItemsCount

    // derivedStateOf — اگر قدر تبدیل نہیں ہوئی تو دوبارہ مرتب نہیں ہوتا
    val scrollProgress by remember {
        derivedStateOf {
            if (total > 0) visibleCount.toFloat() / total else 0f
        }
    }

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

عام غلطیاں: (1) کلید کی کمی — عناصر کسی بھی فہرست تبدیلی پر دوبارہ مرتب ہوتے ہیں؛ (2) اسنیپ شاٹ فلو کے بغیر mutableStateListOf کا استعمال — تبدیلیاں ٹریک نہیں ہو سکتیں؛ (3) itemContent کے اندر suspend فنکشنز کو کال کرنا — ترکیب میں رکاوٹ ڈالتا ہے؛ (4) مخلوط اقسام کے لیے contentType نہ ہونا — Compose ٹیکسٹ پوسٹس کے لیے اشتہار کی ترکیب دوبارہ استعمال کرتا ہے جس سے بصری نمونے پیدا ہوتے ہیں۔ IT Sectr میں ہم تین یا زیادہ مواد کی اقسام والی تمام فہرستوں میں contentType شامل کرتے ہیں۔

اکثر پوچھے گئے سوالات

LazyColumn آہستہ اسکرول ہوتا ہے — کیا کریں؟

تین پیرامیٹرز چیک کریں: (1) key — مستحکم کلید کے بغیر، Compose ترکیب دوبارہ استعمال نہیں کر سکتا، (2) contentType — مختلف عناصر کی اقسام والی فہرستوں کے لیے، (3) beyondBoundsPageCount — تصاویر کے لیے 2 تک بڑھائیں۔ itemContent کے اندر بھاری کمپیوٹیشن کو ڈیٹا کے مطابق کلید کے ساتھ remember میں منتقل کریں۔ سادہ گرافکس کے لیے Image کی بجائے Modifier.drawWithContent استعمال کریں۔

LazyColumn عناصر کے درمیان جدا کرنے والا کیسے شامل کریں؟

عناصر کے درمیان فاصلے کے لیے LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) استعمال کریں۔ لائن کے ساتھ بصری جدا کرنے والے کے لیے، items کے درمیان item { Divider() } شامل کریں۔ خودکار جدا کرنے والا: items(items, key = { it.id }) { item -> ... }، اور ہر عنصر کے درمیان item { HorizontalDivider() } ڈالیں۔ اس کے لیے، LazyListScope.items(list, key) { /* عنصر */ } اور علیحدہ LazyListScope.item { Divider() } استعمال کریں۔

Column کے اندر LazyColumn کام نہیں کرتا — کیوں؟

LazyColumn کی بطور ڈیفالٹ لامحدود اونچائی (fillMaxSize) ہوتی ہے۔ مقررہ اونچائی کے بغیر Column کے اندر، LazyColumn اپنا سائز تعین نہیں کر سکتا۔ حل: (1) LazyColumn پر ایک مقررہ اونچائی سیٹ کریں: Modifier.height(400.dp)، (2) Column کے اندر Modifier.weight(1f) استعمال کریں، (3) LazyColumn کو عمودی طور پر اسکرول قابل کنٹینر کے اندر嵌套 نہ کریں — ہیڈر اور فوٹر کے لیے item {} کے ساتھ LazyColumn کو جڑ عنصر کے طور پر استعمال کریں۔

ڈیٹا تبدیل ہونے پر LazyColumn کو کیسے اپ ڈیٹ کریں؟

LazyColumn خود بخود State تبدیلیوں پر ردعمل ظاہر کرتا ہے۔ اگر ڈیٹا mutableStateListOf یا mutableStateOf میں محفوظ ہے، تو Compose صرف تبدیل شدہ عناصر کو دوبارہ مرتب کرتا ہے۔ ViewModel سے فہرستوں کے لیے، Flow کے ساتھ collectAsState() استعمال کریں۔ کلید کے ساتھ فہرست کو اپ ڈیٹ کرتے وقت، Compose خود بخود Modifier.animateItemPlacement() کے ذریعے تبدیلیوں (اضافہ، حذف، دوبارہ ترتیب) کو متحرک کرتا ہے۔

LazyColumn بمقابلہ LazyVerticalGrid — کون سا منتخب کریں؟

LazyColumn — ایک کالم والی فہرستوں کے لیے (فیڈ، چیٹ، تبصرے)۔ LazyVerticalGrid — گرڈ کے لیے (گیلری، کیٹلاگ، آئیکنز)۔ اگر عناصر فون پر ایک کالم اور ٹیبلیٹ پر دو کالم میں ہونے چاہئیں — GridCells.Adaptive کے ساتھ LazyVerticalGrid استعمال کریں۔ اگر مخلوط گرڈ کی ضرورت ہو (ایک سیکشن میں مختلف کالم نمبر) — LazyColumn استعمال کریں اور items کے اندر افقی LazyRow یا嵌套 کردہ LazyVerticalGrid ڈالیں۔

خلاصہ

  • LazyColumn — اعلانیہ API کے ساتھ سست عمودی فہرستوں کے لیے ایک Jetpack Compose جزو۔
  • items() API ایک فہرست اور ہر عنصر کے لیے DSL بلاک قبول کرتا ہے؛ کارکردگی کے لیے key لازمی ہے۔
  • LazyListState اسکرول پوزیشن کا انتظام کرتا ہے، پروگراماتی اسکرولنگ کے لیے suspend فنکشنز فراہم کرتا ہے۔
  • contentType مختلف عناصر کی اقسام والی فہرستوں کے لیے ترکیب کے پولز کو الگ کرتا ہے۔
  • LazyVerticalGrid / LazyRow — ایک ہی items API کے ساتھ گرڈ اور افقی فہرستوں کے لیے مختلف شکلیں۔
  • LazyColumn SubcomposeLayout اور prefetch بفر کی بدولت 10000+ عناصر کے لیے 60 FPS برقرار رکھتا ہے۔
  • نئے Compose پروجیکٹس کے لیے LazyColumn استعمال کریں؛ View پر مبنی پروجیکٹس کے لیے — RecyclerView۔

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں