RecyclerView — Android Jetpack komponenti, katta ma'lumotlar to'plamlarini ro'yxat va panjara ko'rinishida samarali ko'rsatish uchun. ListView-dan farqli o'laroq, RecyclerView ViewHolder-larni qayta ishlatadi va tartibni LayoutManager orqali boshqaradi. Google (Android Developers, 2026) ma'lumotlariga ko'ra, RecyclerView 1000+ elementli ro'yxatni aylantirishda ViewHolder hovuzi va DiffUtil farq algoritmi tufayli sekundiga 60 kadrgacha qayta ishlaydi. Android ilovalari arxitekturasi haqida batafsil ListView haqidagi maqolamizda o'qing.
Asosiy
RecyclerView — Android Support Library v7 ning bir qismi sifatida Google I/O 2014 da taqdim etilgan Android Jetpack kutubxonasining komponentidir. Dinamik ro'yxat va panjaralarni yuqori samaradorlik bilan ko'rsatish uchun mo'ljallangan. RecyclerView ListView ning o'rnini bosuvchi sifatida paydo bo'ldi va oldingisining asosiy muammosini — ViewHolder-larni majburiy qayta ishlatishning yo'qligini hal qiladi.
RecyclerView arxitekturasi Model-View-Adapter namunasi asosida qurilgan: ma'lumotlar modelda (List, LiveData, Flow) saqlanadi, ko'rsatishni Adapter boshqaradi, tartibni esa LayoutManager nazorat qiladi. Har bir komponent o'z mas'uliyat zonasiga javob beradi, bu tizimni moslashuvchan va kengaytiriladigan qiladi.
Android Developers (2025) so'roviga ko'ra, RecyclerView Google Play top-100 dagi 78% Android ilovalarida qo'llaniladi. 1000+ elementli ro'yxatni aylantirish samaradorligi o'rta segment qurilmalarida uch mexanizm tufayli 60 FPS da barqaror qoladi: ViewHolder hovuzi, yangilanishlarning farq hisobi va asinxron ma'lumot yuklash.
RecyclerView quyidagilar uchun maqbul: noma'lum sonli elementli ro'yxatlar (lentalar, chatlar, loglar), N ustunli panjaralar (galereyalar, kataloglar), kaskad tartiblar (Pinterest taxtalari), element qo'shish/o'chirish animatsiyasi bo'lgan ro'yxatlar. 2-5 elementli oddiy ekranlar uchun LinearLayout yoki ScrollView soddaroq va samaraliroq — RecyclerView qo'shimcha yuk keltiradi.
RecyclerView dan foydalanish uchun build.gradle (app) ga bog'liqlik qo'shing: implementation 'androidx.recyclerview:recyclerview:1.4.0'. Minimal API versiyasi — 14 (Android 4.0). AndroidX RecyclerView 1.3.0 dan boshlab, element tanlash uchun recyclerview-selection va surish uchun recyclerview-swipe modullari mavjud.
RecyclerView uchta mustaqil qatlamga bo'linadi: Adapter ma'lumotlar va ViewHolder-larni boshqaradi, LayoutManager elementlarni joylashtirish uchun javob beradi, ItemAnimator animatsiyalarni nazorat qiladi. Bunday arxitektura boshqa qatlamlarni o'zgartirmasdan istalgan qatlamni almashtirishga imkon beradi — masalan, Adapter kodini o'zgartirmasdan LinearLayoutManager dan GridLayoutManager ga o'tish.
| Komponent | Vazifalari | Tatbiqi |
|---|---|---|
| Adapter | ViewHolder-larni yaratish, ma'lumotlarni View ga bog'lash, o'zgarishlar haqida xabar berish | RecyclerView.Adapter<VH> |
| ViewHolder | View havolalarini keshlash, findViewById() dan qochish | RecyclerView.ViewHolder |
| LayoutManager | Elementlarni joylashtirish, aylantirish yo'nalishini belgilash | LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager |
| ItemAnimator | Element qo'shish, o'chirish, ko'chirish animatsiyasi | DefaultItemAnimator |
| ItemDecoration | Elementlar orasida ajratgichlar, bo'shliqlar, fonlarni chizish | RecyclerView.ItemDecoration |
Ish tsikli: (1) Adapter onCreateViewHolder() orqali ViewHolder yaratadi, (2) LayoutManager ekranda yangi View ning o'rnini belgilaydi, (3) Adapter onBindViewHolder() orqali ma'lumotlarni bog'laydi, (4) aylantirishda ekrandan chiqqan ViewHolder-lar qayta ishlatish uchun hovuzga (RecycledViewPool) tushadi. Yangi View yaratish o'rniga mavjudlari qayta ishlatiladi — bu asosiy samaradorlik mexanizmi.
ViewHolder — ro'yxat elementi ichidagi View larga (TextView, ImageView va h.k.) havolalarni saqlaydigan sinf. ViewHolder bo'lmasa, har bir aylantirishda tizim findViewById() — Android UI ning eng qimmat operatsiyalaridan birini chaqiradi. ViewHolder birinchi bog'lanishdan keyin havolalarni eslab qolib, bu chaqiruvni bartaraf qiladi.
// Ma'lumotlar modeli
data class Article(
title: String,
summary: String,
author: String,
imageUrl: String?
)
// ViewHolder — View ga havolalarni saqlaydi
class ArticleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val titleText = itemView.findViewById<TextView>(R.id.tvTitle)
private val summaryText = itemView.findViewById<TextView>(R.id.tvSummary)
private val authorText = itemView.findViewById<TextView>(R.id.tvAuthor)
fun bind(article: Article) {
titleText.text = article.title
summaryText.text = article.summary
authorText.text = article.author
}
}
Amaliy qoida: element tartibidagi har bir View ViewHolder xususiyati sifatida findViewById() bilan aniq bir marta — konstruktorda e'lon qilinishi kerak. bind() metodi findViewById() ni chaqirmaydi, faqat matn, ranglar va tinglovchilarni o'rnatadi. Bu yondashuv Google (Android Performance Patterns, 2025) ma'lumotlariga ko'ra ro'yxat aylantirishni 30-50% tezlashtiradi.
LayoutManager elementlarning RecyclerView ichida qanday joylashishini belgilaydi. Standart holda Android uchta tatbiqni taqdim etadi: LinearLayoutManager, GridLayoutManager va StaggeredGridLayoutManager. LayoutManager tanlovi foydalanuvchining ma'lumotlarni idrok etishiga va aylantirish samaradorligiga ta'sir qiladi.
| LayoutManager | Joylashuv | Qachon ishlatiladi | O'rnatish usuli |
|---|---|---|---|
| LinearLayoutManager | Ro'yxat (vertikal yoki gorizontal) | Lentalar, chatlar, bildirishnomalar, mahsulot ro'yxatlari | LinearLayoutManager(context) |
| GridLayoutManager | N ustunli panjara | Galereyalar, kataloglar, piktogrammalar, rasm panjarasi | GridLayoutManager(context, spanCount) |
| StaggeredGridLayoutManager | Kaskad panjara (turli balandlikdagi elementlar) | Pinterest taxtalari, eslatmalar, masonry galereyalar | StaggeredGridLayoutManager(spanCount, orientation) |
// LinearLayoutManager ni Fragment da o'rnatish
class ArticleListFragment : Fragment() {
private lateinit var binding: FragmentArticleListBinding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val recyclerView = binding.recyclerView
recyclerView.layoutManager = LinearLayoutManager(requireContext())
recyclerView.adapter = ArticleAdapter(articlesList)
// Optimallashtirish: qat'iy o'lcham + hovuz
recyclerView.setHasFixedSize(true)
recyclerView.setItemViewCacheSize(20)
// Elementlar orasidagi ajratgich
val divider = DividerItemDecoration(requireContext(), LinearLayoutManager.VERTICAL)
recyclerView.addItemDecoration(divider)
}
}
Samaradorlik: vertikal aylantirish bilan LinearLayoutManager eng tezkor variant, chunki elementlar ketma-ket joylashadi va LayoutManager pozitsiyalarni O(1) bilan hisoblaydi. GridLayoutManager ustunlarga bo'lish uchun qo'shimcha hisoblashlarni talab qiladi, lekin sobit spanCount bilan samarali qoladi. StaggeredGridLayoutManager uchtasi ichida eng sekin, chunki u qo'shni elementlarning balandligini hisobga olib, kaskaddagi element pozitsiyasini hisoblashi kerak. Faqat hujayralarning turli balandligi vizual talab qilinganda foydalaning.
Adapter RecyclerView da GoF dan Adapter namunasini tatbiq qiladi: ma'lumotlarni (List<T>) ekranda ko'rsatiladigan ViewHolder larga aylantiradi. Ma'lumotlar o'zgarganda, Adapter RecyclerView ni notifyDataSetChanged(), notifyItemInserted() va shu kabi metodlar orqali xabardor qilishi mumkin. Muammo shundaki, notifyDataSetChanged() barcha ko'rinadigan elementlarni qayta chizadi, bu esa tebranishlarga (jank) olib keladi.
// DiffUtil bilan samarali yangilash uchun Adapter
class ArticleAdapter : RecyclerView.Adapter<ArticleViewHolder>() {
private var articles: List<Article> = emptyList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_article, parent, false)
return ArticleViewHolder(view)
}
override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
holder.bind(articles[position])
}
override fun getItemCount(): Int = articles.size
// Ro'yxatni DiffUtil orqali yangilash
fun updateArticles(newArticles: List<Article>) {
val diffCallback = ArticleDiffCallback(articles, newArticles)
val diffResult = DiffUtil.calculateDiff(diffCallback)
articles = newArticles
diffResult.dispatchUpdatesTo(this)
}
}
// DiffUtil uchun Callback
class ArticleDiffCallback(
private val oldList: List<Article>,
private val newList: List<Article>
) : DiffUtil.Callback() {
override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size
override fun areItemsTheSame(oldPos: Int, newPos: Int): Boolean {
return oldList[oldPos].title == newList[newPos].title
}
override fun areContentsTheSame(oldPos: Int, newPos: Int): Boolean {
return oldList[oldPos] == newList[newPos]
}
}
DiffUtil eski ro'yxatni yangisiga aylantirish uchun minimal operatsiyalar sonini (insert, remove, move, change) hisoblaydigan Eugene W. Myers farq algoritmidan foydalanadi. 100 elementli ro'yxat uchun DiffUtil 1-5 ms ichida ishlaydi (Google, 2025). Katta ro'yxatlar (10000+) uchun AsyncListDiffer yoki Paging kutubxonasidan PagingDataAdapter dan foydalaning — ular hisoblashlarni fon oqimida bajaradi.
ListView — Android 1.0 (API 1) da paydo bo'lgan RecyclerView ning o'tmishdoshidir. U ham ro'yxatlarni ko'rsatadi, lekin ViewHolder ni majburlamaydi, LayoutManager ni qo'llab-quvvatlamaydi va o'zgarishlarni animatsiya qila olmaydi. RecyclerView qat'iyroq arxitektura va samaradorlik bilan ListView ning o'rnini bosuvchi sifatida ishlab chiqilgan.
| Mezon | RecyclerView | ListView |
|---|---|---|
| ViewHolder | Majburiy (arxitektura) | Tavsiya etiladi, lekin majburiy emas |
| LayoutManager | Bo'linish: ro'yxat, panjara, kaskad | Faqat vertikal ro'yxat |
| O'zgarish animatsiyasi | DefaultItemAnimator o'rnatilgan | O'rnatilgan qo'llab-quvvatlash yo'q |
| O'zgarishlar haqida xabar | Nuqtaviy: notifyItemInserted/Removed | notifyDataSetChanged() faqat butun ro'yxat |
| DiffUtil | DiffUtil.Callback orqali qo'llab-quvvatlash | Ekvivalenti yo'q |
| Ajratgichlar | ItemDecoration (shaxsiy) | android:divider (o'rnatilgan) |
| Minimal versiya | API 14 (Android 4.0) AndroidX orqali | API 1 (barcha versiyalar) |
Google tavsiyasi (Android Developers, 2026): barcha yangi loyihalar uchun RecyclerView dan foydalaning. ListView eski kod bazalarida (legacy) qoldirilishi mumkin, bu yerda migratsiya xarajatlarni oqlamaydi. RecyclerView 100+ elementda yaxshiroq samaradorlikni ta'minlaydi, gorizontal aylantirish va panjaralarni qo'shimcha vositalarsiz qo'llab-quvvatlaydi. Android 15 da ListView rasman qisman eskirgan deb belgilangan.
Tez-tez beriladigan savollar
Uchta shartni tekshiring: (1) Adapter recyclerView.adapter = adapter orqali o'rnatilgan, (2) LayoutManager recyclerView.layoutManager = LinearLayoutManager(context) orqali o'rnatilgan, (3) ro'yxatdagi ma'lumotlar bo'sh emas va adapter xabardor qilingan (notifyDataSetChanged()). Oddiy xato — notifyDataSetChanged() chaqiruvidan keyin ma'lumotlarni o'rnatish. Ma'lumotlar xabardor qilishdan oldin tayinlanishi kerak. Ro'yxat hajmini tekshiring: adapter.itemCount 0 dan katta bo'lishi kerak.
Sekinlashishlar aylantirishda (jank) onBindViewHolder() og'ir operatsiyalarni bajarganida yuz beradi: keshlashsiz rasmlarni yuklash, bind ichida findViewById(), murakkab hisoblashlar. Yechimlar: (1) asinxron rasm yuklash uchun Glide yoki Coil kutubxonasidan foydalaning, (2) barcha findViewById() larni ViewHolder konstruktoriga olib chiqing, (3) farq hisoblashlari uchun AsyncListDiffer dan foydalaning. Sekin kadrlarni topish uchun Android Studio da GPU profillashni (Profile GPU Rendering) yoqing.
LayoutManager ga orientatsiyani uzating: LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false). Ikkinchi parametr reverseLayout (false = chapdan o'ngga). Gorizontal panjara uchun gorizontal orientatsiya bilan GridLayoutManager yoki sahifali aylantirish uchun shaxsiy LinearSnapHelper dan foydalaning. Gorizontal ro'yxatlar mahsulot karusellari, rasmlar, kategoriyalar uchun yaxshi mos keladi.
RecyclerView da o'rnatilgan onClickListener yo'q (ListView dagi onItemClickListener dan farqli o'laroq). Uni ViewHolder da tatbiq qiling: konstruktorga lambda uzating va itemView.setOnClickListener ni o'rnating. Misol: class ArticleViewHolder(itemView: View, val onItemClick: (Article) -> Unit) : RecyclerView.ViewHolder(itemView). bind() ichida onItemClick(article) ni chaqiring. Muqobil — imo-ishoralarni boshqarish uchun RecyclerView.addOnItemTouchListener() ni o'rnating.
RecycledViewPool — aylantirishda ko'rinmas bo'lib qolgan ViewHolder larning ichki hovuzi. Yo'q qilish o'rniga hovuzda saqlanadi va qayta ishlatiladi. Standart hovuz har bir turdan 5 ta ViewHolder ni saqlaydi. Murakkab tartiblar uchun hajmni oshiring: recyclerView.getRecycledViewPool().setMaxRecycledViews(VIEW_TYPE_NORMAL, maxCount). RecyclerView da bir necha View turi (viewType) bo'lsa, hovuz har biri uchun alohida steklarni saqlaydi. RecycledViewPool ni turli RecyclerView lar o'rtasida birgalikda ishlatish ichki ro'yxatli ekranlarda xotirani tejaydi.
Xulosa
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.