ListView — API 1 (Android 1.0) dan boshlab mavjud bo'lgan, vertikal ro'yxatlarni ko'rsatish uchun asosiy Android komponenti. ListView ArrayAdapter yordamida elementlardan ro'yxat yaratadi va maxsus hujayra maketlarini qo'llab-quvvatlaydi. ListView nima ekanligini, uni qanday sozlashni va bu eski, ammo hali ham ishlatiladigan komponent qanday tuzoqlarni yashirishini tushunamiz. IT Sectr-da biz ListView-ni legacy-loyihalarda uchratamiz va Android 4.4 bilan orqaga moslikni qo'llab-quvvatlaymiz. Zamonaviy muqobil bilan solishtirish uchun RecyclerView haqidagi maqolani o'qing.
Asosiy
ListView — android.widget paketidan, aylantiriladigan elementlar ro'yxatini ko'rsatish uchun mo'ljallangan View guruhi. ListView AdapterView namunasini amalga oshiradi: ma'lumotlar adapter (Adapter) orqali uzatiladi, u ma'lumot elementlarini ekranda ko'rsatiladigan View-ga aylantiradi. ListView Android SDK-da birinchi versiyadan (API 1) mavjud va qo'shimcha kutubxonalarni talab qilmaydi.
Arxitektura ListView RecyclerView-dan soddaroq: LayoutManager o'rnatilgan (faqat vertikal aylantirish), o'zgarishlar animatsiyasi yo'q, ajratgichlar android:divider XML atributi orqali o'rnatiladi. ListView avtomatik ravishda OverScrollView va fokusda ajratib ko'rsatishni qo'shadi, bu prototiplashni soddalashtiradi. Statista (2025) ma'lumotlariga ko'ra, Play Store top-100 dagi Android ilovalarining taxminan 15% i hali ham ListView-ni o'z ichiga oladi — asosan minimal qo'llab-quvvatlangan legacy-loyihalar.
ListView 2008 yildan 2014 yilgacha Android-da ro'yxatlarning asosiy komponenti bo'lgan, Google I/O 2014 da RecyclerView taqdim etilgan. Qisman eskirgan (soft-deprecated) maqomiga qaramay, ListView Android-ning barcha versiyalarida mavjud bo'lib qoladi va SDK API 35 da @Deprecated sifatida belgilanmagan. Loyihangiz Android 4.4 (API 19) va undan pastini qo'llab-quvvatlasa, ListView yagona o'rnatilgan tanlovdir, chunki RecyclerView AndroidX va gradle bog'liqliklarini talab qiladi.
ArrayAdapter — ListView uchun eng mashhur adapter. U List<T> va har bir element uchun maketni qabul qiladi. Odatiy bo'lib ArrayAdapter har bir ob'ekt uchun toString() ni chaqiradi va matnni simple_list_item_1 da (bitta TextView) ko'rsatadi. Maxsus ko'rinish uchun getView() ni qayta yozish yoki konstruktorga maxsus maketni uzatish kerak.
// ArrayAdapter bilan ListView (oddiy matn)
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val countries = listOf(
"Rossiya", "AQSH", "Germaniya",
"Fransiya", "Yaponiya", "Xitoy", "Braziliya"
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val adapter = ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,
countries
)
binding.listView.adapter = adapter
// Bosishni boshqarish
binding.listView.onItemClickListener =
AdapterView.OnItemClickListener { _, _, position, _ ->
Toast.makeText(this, countries[position], Toast.LENGTH_SHORT).show()
}
}
}
SimpleAdapter Map-ma'lumotlardan ro'yxatlar uchun mo'ljallangan. U List<Map<String, Any>> va Map kalitlarini maketdagi vidjetlar ID si bilan bog'lash uchun from/to massivini qabul qiladi. SimpleAdapter alohida adapter klassi kerak bo'lmaganda tezkor prototiplar uchun qulay. Kamchiliklari: type-safe tipizatsiyaning yo'qligi va maxsus mantiq bilan murakkablik.
<!-- ListView bilan maket -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/divider"
android:dividerHeight="1px"
android:scrollbars="vertical" />
</LinearLayout>
Maxsus adapter ListView uchun getView() metodini qayta yozadi, RecyclerView buni onCreateViewHolder + onBindViewHolder ga ajratadi. ListView-da ikkala qadam birlashtirilgan, shuning uchun dasturchi ViewHolder namunasini convertView (qayta ishlatiladigan View) va setTag() tegi orqali mustaqil amalga oshirishi kerak.
// Ma'lumotlar modeli
data class Product(
name: String,
price: String,
imageResId: Int
)
// ViewHolder bilan maxsus adapter
class ProductAdapter(
context: Context,
private val products: List<Product>
) : ArrayAdapter<Product>(context, 0, products) {
// Keshlash uchun ViewHolder
private class ViewHolder(view: View) {
val nameText: TextView = view.findViewById(R.id.tvName)
val priceText: TextView = view.findViewById(R.id.tvPrice)
val imageView: ImageView = view.findViewById(R.id.ivProduct)
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: LayoutInflater.from(context)
.inflate(R.layout.item_product, parent, false)
.also { it.tag = ViewHolder(it) }
val holder = view.tag as ViewHolder
val product = getItem(position)
holder.nameText.text = product.name
holder.priceText.text = product.price
holder.imageView.setImageResource(product.imageResId)
return view
}
}
RecyclerView-dan asosiy farq: ListView-da getView() metodi elementning ekranda har ko'rinishida chaqiriladi. Agar convertView va ViewHolder ishlatilmasa, har bir aylantirish yangi View ob'ektini yaratadi, bu esa 50+ elementli ro'yxatlarda xotira oqishiga va sekinlashuvga olib keladi. ViewHolder view.tag bilan — maxsus maketli ListView uchun majburiy optimallashtirish.
ListView to'rtta arxitektura chekloviga ega, Google ularni RecyclerView-da tuzatgan: (1) faqat vertikal yo'nalish — tarmoqlar, gorizontal ro'yxatlar yoki kaskadlar yo'q; (2) nuqtali bildirishnomalarning yo'qligi — har qanday ma'lumot o'zgarishi notifyDataSetChanged() orqali to'liq qayta chizishga olib keladi, bu esa silkinishlarni keltirib chiqaradi; (3) elementlarni qo'shish/o'chirish uchun o'rnatilgan animatsiyaning yo'qligi; (4) mas'uliyatlarning ajratilmaganligi — LayoutManager o'rnatilgan, ItemAnimator mavjud emas.
<!-- item_product.xml — ListView elementi maketi -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="12dp">
<ImageView
android:id="@+id/ivProduct"
android:layout_width="56dp"
android:layout_height="56dp"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingStart="12dp">
<TextView
android:id="@+id/tvName"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvPrice"
android:textSize="14sp"
android:textColor="@color/price" />
</LinearLayout>
</LinearLayout>
Amaliy oqibatlar: 20 elementgacha bo'lgan ro'yxatlarda ListView RecyclerView kabi tez ishlaydi. 100+ elementda farq sezilarli bo'ladi: ListView diff-hisoblashlarning yo'qligi va majburiy ViewHolder tufayli FPS yo'qotishni boshlaydi. Tez-tez yangilanadigan ro'yxatlar (chat, feed, loglar) uchun ListView mos emas — Paging 3 bilan RecyclerView dan foydalaning. IT Sectr-da biz 50 dan ortiq elementli legacy-ekranlarda har qanday ishda ListView-ni RecyclerView-ga migratsiya qilamiz.
ListView kodsiz tezkor sozlash uchun XML atributlari to'plamini taqdim etadi: android:divider (ajratgichning rangi/tasviri), android:dividerHeight (qalinligi), android:scrollbars (aylantirish chiziqlari), android:fastScrollEnabled (tutqich bilan tez aylantirish), android:choiceMode (tanlash rejimi: singleChoice, multipleChoice). android:entries atributi adaptersiz ro'yxatni resurslar massividan (string-array) to'ldirishga imkon beradi.
| Atribut | Tavsif | Misol qiymat |
|---|---|---|
| android:divider | Ajratgichning rangi yoki drawable | @color/gray_light |
| android:dividerHeight | Ajratgichning qalinligi px/dp da | 1dp |
| android:entries | Resurslardan satrlar massivi | @array/countries |
| android:choiceMode | Element tanlash rejimi | singleChoice |
| android:fastScrollEnabled | Tez aylantirish | true |
| android:overlapAnchor | Ochiladigan ro'yxatlar uchun langar (API 21+) | true |
Tanlash rejimi: choiceMode="singleChoice" RadioButton uslubini yoqadi, bunda tanlangan element ajratib ko'rsatiladi. choiceMode="multipleChoice" — bir nechta elementlar uchun belgilash katakchalari. Tanlash ma'lumotlari listView.checkedItemPosition yoki listView.checkedItemIds orqali mavjud. Muhim: choiceMode da ListView fon uchun StateListDrawable dan foydalanadi — standart ko'k dizaynga mos kelmasa, o'z selektoringizni o'rnating.
Tanlov ListView va RecyclerView o'rtasida loyiha talablariga bog'liq. RecyclerView zamonaviy standartdir, ammo ListView eski kodni saqlash uchun minimal xarajatli oddiy ekranlar uchun asoslanishi mumkin. Barcha asosiy parametrlar bo'yicha taqqoslash:
| Parametr | ListView | RecyclerView |
|---|---|---|
| Kutubxona hajmi | SDK-ga o'rnatilgan (≈60 KB) | AndroidX (bog'liqliklar bilan ≈300 KB) |
| Minimal versiya | API 1 | API 14 (AndroidX orqali) |
| Yo'nalish | Faqat vertikal | Vertikal, gorizontal, tarmoq, kaskad |
| ViewHolder | Qo'lda amalga oshirish | Arxitektura bo'yicha majburiy |
| Animatsiya | Faqat fade o'tishlar | DefaultItemAnimator (add, remove, move, change) |
| Nuqtali yangilanishlar | Yo'q (faqat notifyDataSetChanged) | notifyItemInserted/Removed/Changed |
| Click listener | onItemClickListener (o'rnatilgan) | ViewHolder orqali (o'rnatilgani yo'q) |
| Ishlash | 50 elementgacha ro'yxatlar uchun yetarli | 1000+ element uchun barqaror 60 FPS |
Xulosa: yangi loyihalar uchun RecyclerView dan foydalaning. ListView ni faqat migratsiya asossiz qimmat bo'lgan legacy-kodda qoldiring. Material Design 3 (2026) ko'rsatmalariga ko'ra, har qanday murakkablikdagi ro'yxatlar zamonaviy ishlash va foydalanish qulayligi standartlariga mos kelish uchun RecyclView dan foydalanishi kerak.
Tez-tez beriladigan savollar
ListView Android SDK API 35 da @Deprecated sifatida belgilanmagan, ammo Google yangi loyihalarda uni ishlatishni tavsiya etmaydi (soft-deprecated). Komponent Android-ning barcha versiyalarida ishlaydi. RecyclerView 2014 yildan beri rasmiy o'rnini bosuvchidir. Agar yangi loyiha boshlasangiz — RecyclerView ni tanlang. Agar mavjud loyihani qo'llab-quvvatlasangiz — ListView o'zgarishsiz ishlashda davom etadi.
ListView addHeaderView(View, Object, boolean) va addFooterView(View, Object, boolean) metodlarini qo'llab-quvvatlaydi. Header va footer elementlarning umumiy ro'yxatiga qo'shiladi, lekin adapterda ishtirok etmaydi — ular doimo ro'yxatning boshida va oxirida ko'rsatiladi. Muhim: header/footer ni adapter o'rnatishdan oldin qo'shing (setAdapter()), aks holda ular hisobga olinmaydi. Header qo'shilgandan keyin element pozitsiyalari ID lari headerlar soniga siljiydi.
ListView va ScrollView ikkalasi ham vertikal imo-ishoralarni qayta ishlaydi, bu esa ziddiyatni keltirib chiqaradi: tashqi ScrollView aylantirishni ushlab qoladi va ListView aylanmaydi. Yechim: (1) ListView ni ScrollView ga joylashtirmang — NestedScrollingChild bilan RecyclView dan foydalaning, (2) ScrollView ni NestedScrollView (API 21+) bilan almashtiring, (3) ScrollView ichida qat'iy balandlikdagi (android:layout_height="...dp") ListView dan foydalaning, ammo bu moslashuvchanlikni buzadi.
ListView da ma'lumotlarni tozalash adapter turiga bog'liq. ArrayAdapter uchun: adapter.clear() va adapter.addAll(newList) keyin adapter.notifyDataSetChanged(). Maxsus adapter uchun: ma'lumotlar ro'yxatini yangilang va notifyDataSetChanged() ni chaqiring. Diqqat: listView.invalidateViews() faqat View ni qayta chizadi, lekin ma'lumotlarni yangilamaydi. Har doim ma'lumotlarni to'g'ridan-to'g'ri emas, adapter orqali o'zgartiring.
ListView elementining balandligi item-maketida o'rnatiladi. Agar maket layout_height="wrap_content" dan foydalansa, balandlik tarkibga moslashadi. Barcha elementlar uchun qat'iy balandlik uchun getView() da LayoutParams o'rnatadigan maxsus adapterdan foydalaning: view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight). Turli balandliklar uchun har xil ko'rinish turlari bilan RecyclerView dan foydalaning.
Yakun
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.