LazyColumn در Jetpack Compose — چیست، ویژگی‌ها و نحوه کار

نویسنده: IT Sectr منتشر شده: 2026-06-29 زمان مطالعه: 11 دقیقه

LazyColumn یک تابع composable در Jetpack Compose برای ایجاد لیست‌های عمودی با بارگذاری تنبل عناصر است. بر خلاف Column، LazyColumn فقط عناصر قابل مشاهده روی صفحه را ایجاد و ترکیب می‌کند و هنگام اسکرول آن‌ها را مجدداً استفاده می‌کند. به گفته Google Android Documentation, 2025, LazyColumn ابزار اصلی برای نمایش مجموعه داده‌های بزرگ در برنامه‌های موبایل به دلیل مدیریت کارآمد حافظه است.

نکات اصلی

  • LazyColumn لیست عمودی Jetpack Compose با بارگذاری تنبل است که فقط عناصر قابل مشاهده را ایجاد کرده و هنگام اسکرول آن‌ها را مجدداً استفاده می‌کند.
  • items مجموعه داده و تابع کارخانه برای ایجاد عناصر لیست را می‌پذیرد و item مؤلفه‌های تکی اضافه می‌کند.
  • LazyListState موقعیت اسکرول را ردیابی کرده و امکان کنترل برنامه‌ریزی شده لیست را از طریق animateScrollToItem و scrollToItem فراهم می‌کند.
  • Sticky headers با استفاده از stickyHeader عنوان بخش‌ها را هنگام اسکرول در بالای لیست ثابت می‌کنند.
  • LazyColumn انواع مختلف عناصر را از طریق پارامتر contentType برای بهینه‌سازی استفاده مجدد پشتیبانی می‌کند.

LazyColumn در Jetpack Compose چیست

LazyColumn یک تابع composable است که یک لیست عمودی قابل اسکرول با بارگذاری تنبل را پیاده‌سازی می‌کند. بر خلاف Column که همه عناصر فرزند را یکباره رندر می‌کند، LazyColumn فقط عناصری را که در ناحیه نمایش قرار می‌گیرند ایجاد می‌کند.

مکانیزم بارگذاری تنبل در LazyColumn بر اساس استفاده مجدد از عناصر است: وقتی عنصری در حین اسکرول پنهان می‌شود، ترکیب و چیدمان آن می‌تواند برای عنصر جدید نمایش داده شده مجدداً استفاده شود. این کار به ویژه در لیست‌های طولانی در حافظه و زمان پردازنده صرفه‌جویی می‌کند.

به گفته Android Developers Blog, 2024, LazyColumn می‌تواند لیست‌های ده‌ها هزار عنصری را بدون کاهش قابل توجه عملکرد به طور مؤثر پردازش کند. هر عنصر در LazyColumn یک کلید (key) دارد که به Compose کمک می‌کند هنگام تغییرات لیست، عنصر را شناسایی کرده و وضعیت آن را حفظ کند.

امضای پایه LazyColumn

LazyColumn پارامترهای modifier, state, contentPadding, reverseLayout, verticalArrangement و horizontalAlignment را می‌پذیرد. محتوا در بلوک لامبدا از طریق توابع DSL items و item تعیین می‌شود.

kotlin
@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")
        }
    }
}

پارامترهای LazyColumn: items و item

بلوک DSL LazyColumn توابع items و item را برای افزودن محتوا فراهم می‌کند. items مجموعه داده، کلید و تابع کارخانه برای ایجاد عناصر را می‌پذیرد. item یک عنصر ایستا به لیست اضافه می‌کند.

itemsIndexed نوعی از items است که علاوه بر داده، اندیس عنصر را نیز منتقل می‌کند. این زمانی مفید است که موقعیت عنصر بدون محاسبه جداگانه مورد نیاز باشد. items(size) فقط تعداد عناصر و کارخانه را بدون وابستگی به مجموعه می‌پذیرد.

پارامتر key در items هر عنصر را به طور یکتا شناسایی می‌کند. به گفته Material Design Guidelines, 2025, کلیدها عملکرد را در هنگام به‌روزرسانی و انیمیشن عناصر بهبود می‌بخشند، زیرا Compose می‌تواند جابجایی یا تغییر یک عنصر خاص را از طریق کلید ردیابی کند.

مثال با انواع مختلف عناصر

تابع items با contentType به LazyColumn اجازه می‌دهد استفاده مجدد از عناصر با انواع مختلف را بهینه کند. در مثال زیر، در یک لیست از عنوان‌بخش‌ها و ردیف‌های معمولی استفاده شده است.

kotlin
@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 و کنترل اسکرول

LazyListState یک شیء وضعیت LazyColumn است که موقعیت فعلی اسکرول، اولین عنصر قابل مشاهده و جابجایی را ردیابی می‌کند. این شیء می‌تواند از طریق rememberLazyListState() ایجاد شده و به پارامتر state LazyColumn منتقل شود.

LazyListState متدهای animateScrollToItem و scrollToItem را برای اسکرول برنامه‌ریزی شده به یک عنصر خاص فراهم می‌کند. animateScrollToItem یک انیمیشن روان اسکرول ایجاد می‌کند و scrollToItem بلافاصله اسکرول می‌کند. هر دو متد نیاز به فراخوانی در داخل یک کوروتین در CompositionContext دارند.

به گفته Android Developers, 2024, LazyListState همچنین شامل layoutInfo است که اطلاعاتی درباره عناصر قابل مشاهده — اندیس‌ها، جابجایی‌ها و اندازه‌های آن‌ها — ارائه می‌دهد. این برای پیاده‌سازی تحلیل، ردیابی بازدیدها یا اسکرول بی‌نهایت مفید است.

مثال با اسکرول برنامه‌ریزی شده

در این مثال LazyColumn از طریق LazyListState کنترل می‌شود. دکمه لیست را با انیمیشن روان به عنصر با اندیس 50 اسکرول می‌کند.

kotlin
@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

عامل کلیدی عملکرد 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 استفاده کنید

Sticky headers و بخش‌ها در LazyColumn

stickyHeader تابع DSL LazyColumn است که عنوان بخش را هنگام اسکرول در بالای لیست ثابت می‌کند. وقتی بخش بعدی به بالا می‌رسد، عنوان آن جایگزین عنوان فعلی می‌شود. این رفتار برای کاربران از لیست مخاطبین و تقویم‌ها آشناست.

stickyHeader مانند item یک کلید و تابع کارخانه می‌پذیرد. بر خلاف item معمولی، stickyHeader هنگام اسکرول محتوای بخش خود قابل مشاهده می‌ماند. وقتی بخش به طور کامل اسکرول شد، عنوان بخش بعدی عنوان قبلی را کنار می‌زند.

به گفته Material Design Guidelines, 2025, sticky header ناوبری را در لیست‌های طولانی بهبود می‌بخشد و بار شناختی کاربر را کاهش می‌دهد. برای پیاده‌سازی sticky header کافی است عنوان بخش را در موقعیت صحیح نسبت به عناصر items در stickyHeader قرار دهید.

kotlin
@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))
            }
        }
    }
}

سوالات متداول

LazyColumn در Compose چه تفاوتی با Column دارد؟

Column همه عناصر را یکباره رندر کرده و برای لیست‌های تا 20–30 عنصر مناسب است. LazyColumn فقط عناصر قابل مشاهده را ایجاد کرده و هنگام اسکرول آن‌ها را مجدداً استفاده می‌کند که امکان کار با هزاران عنصر بدون افت عملکرد را فراهم می‌کند.

چگونه بین عناصر LazyColumn جداکننده اضافه کنیم؟

از Arrangement.spacedBy در پارامتر verticalArrangement یا توابع items با جداکننده از طریق اندیس استفاده کنید. برای جداکننده‌های پیچیده، یک item جداگانه با Divider() بین عناصر لیست اضافه کنید.

چگونه LazyColumn را هنگام تغییر داده به‌روزرسانی کنیم؟

LazyColumn هنگام تغییر مجموعه داده در صورت استفاده از کلیدهای پایدار به طور خودکار ترکیب مجدد می‌شود. تغییرات داده که از طریق mutableStateListOf یا StateFlow تشخیص داده می‌شوند منجر به بازترسیم فقط عناصر تغییر یافته می‌شوند.

آیا می‌توان LazyColumn را درون LazyColumn قرار داد؟

قرار دادن مستقیم LazyColumn درون LazyColumn توصیه نمی‌شود — هر دو اسکرول مستقل دارند که تضاد ژست ایجاد می‌کند. به جای آن از Column معمولی با LazyColumn درون بخش قابل اسکرول یا LazyVerticalGrid برای شبکه‌ها استفاده کنید.

چگونه تشخیص دهیم که LazyColumn تا انتها اسکرول شده است؟

از LazyListState.layoutInfo.visibleItemsInfo استفاده کنید و اندیس آخرین عنصر قابل مشاهده را با تعداد کل عناصر مقایسه کنید. برای اسکرول بی‌نهایت، زمانی که آخرین عنصر قابل مشاهده به انتهای لیست نزدیک می‌شود را ردیابی کنید.

خلاصه

  • LazyColumn لیست عمودی با بارگذاری تنبل است که عناصر را فقط در ناحیه نمایش برای کار مؤثر با داده‌های بزرگ ایجاد کرده و مجدداً استفاده می‌کند.
  • items و item توابع DSL برای افزودن مجموعه داده‌ها و مؤلفه‌های تکی در LazyColumn با پشتیبانی از کلیدها و contentType هستند.
  • LazyListState موقعیت اسکرول را مدیریت کرده و ناوبری برنامه‌ریزی شده را از طریق animateScrollToItem و scrollToItem در کوروتین‌ها فراهم می‌کند.
  • contentType و key ابزارهای اصلی بهینه‌سازی عملکرد هستند که ترکیب مجدد را کاهش داده و استفاده مجدد از عناصر را بهبود می‌بخشند.
  • stickyHeader عنوان‌بخش‌ها را در بالای لیست ثابت می‌کند و ناوبری را در لیست‌های طولانی با گروه‌بندی داده بهبود می‌بخشد.
  • Arrangement.spacedBy و contentPadding فاصله بین عناصر و لبه‌های LazyColumn را برای مطابقت با Material Design مدیریت می‌کنند.
  • برای لیست‌های افقی با بارگذاری تنبل از LazyRow و برای شبکه‌ها از LazyVerticalGrid با همان اصل بارگذاری تنبل استفاده کنید.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید