ListView एक बुनियादी Android घटक है जो वर्टिकल सूचियाँ प्रदर्शित करने के लिए है, जो API 1 (Android 1.0) से उपलब्ध है। ListView ArrayAdapter का उपयोग करके तत्वों की एक सूची बनाता है और कस्टम सेल लेआउट का समर्थन करता है। आइए जानें कि ListView क्या है, इसे कैसे कॉन्फ़िगर करें और यह पुराना लेकिन अभी भी उपयोग किया जाने वाला घटक क्या समस्याएँ छिपाता है। IT Sectr में हम लीगेसी प्रोजेक्ट्स में ListView देखते हैं और Android 4.4 के साथ बैकवर्ड कम्पैटिबिलिटी बनाए रखते हैं। आधुनिक विकल्प से तुलना के लिए, RecyclerView के बारे में लेख पढ़ें।
मुख्य बिंदु
ListView android.widget पैकेज का एक ViewGroup है जो तत्वों की एक स्क्रॉल करने योग्य सूची प्रदर्शित करने के लिए डिज़ाइन किया गया है। ListView AdapterView पैटर्न लागू करता है: डेटा एक एडाप्टर (Adapter) के माध्यम से पास किया जाता है, जो डेटा तत्वों को स्क्रीन पर प्रदर्शित Views में परिवर्तित करता है। ListView पहले संस्करण (API 1) से Android SDK में मौजूद है और इसे अतिरिक्त लाइब्रेरी की आवश्यकता नहीं है।
आर्किटेक्चर ListView का RecyclerView से सरल है: LayoutManager अंतर्निहित है (केवल वर्टिकल स्क्रॉलिंग), परिवर्तन एनिमेशन अनुपस्थित हैं, विभाजक android:divider XML विशेषता के माध्यम से सेट किए जाते हैं। ListView स्वचालित रूप से OverScrollView और फ़ोकस हाइलाइटिंग जोड़ता है, जो प्रोटोटाइपिंग को सरल बनाता है। Statista (2025) के अनुसार, Play Store के शीर्ष 100 में लगभग 15% Android ऐप्स में अभी भी ListView है — मुख्य रूप से न्यूनतम समर्थन वाली लीगेसी परियोजनाएँ।
ListView 2008 से 2014 तक Android में मुख्य सूची घटक था, जब Google I/O 2014 में RecyclerView पेश किया गया था। आंशिक रूप से अप्रचलित (soft-deprecated) होने के बावजूद, ListView Android के सभी संस्करणों में उपलब्ध है और SDK API 35 में @Deprecated के रूप में चिह्नित नहीं है। यदि आपका प्रोजेक्ट Android 4.4 (API 19) और उससे नीचे का समर्थन करता है, तो ListView एकमात्र अंतर्निहित विकल्प है, क्योंकि RecyclerView के लिए AndroidX और Gradle निर्भरताएँ आवश्यक हैं।
ArrayAdapter ListView के लिए सबसे लोकप्रिय एडाप्टर है। यह प्रत्येक आइटम के लिए List<T> और एक लेआउट स्वीकार करता है। डिफ़ॉल्ट रूप से, ArrayAdapter प्रत्येक ऑब्जेक्ट पर toString() कॉल करता है और simple_list_item_1 (एक TextView) में टेक्स्ट प्रदर्शित करता है। कस्टम डिस्प्ले के लिए, आपको getView() को ओवरराइड करना होगा या कंस्ट्रक्टर में कस्टम लेआउट पास करना होगा।
// ArrayAdapter के साथ ListView (सरल टेक्स्ट)
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val countries = listOf(
"रूस", "अमेरिका", "जर्मनी",
"फ़्रांस", "जापान", "चीन", "ब्राज़ील"
)
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
// क्लिक हैंडलिंग
binding.listView.onItemClickListener =
AdapterView.OnItemClickListener { _, _, position, _ ->
Toast.makeText(this, countries[position], Toast.LENGTH_SHORT).show()
}
}
}
SimpleAdapter Map डेटा से सूचियों के लिए डिज़ाइन किया गया है। यह List<Map<String, Any>> और Map कुंजियों को लेआउट में विजेट ID से बाँधने के लिए from/to ऐरे स्वीकार करता है। SimpleAdapter त्वरित प्रोटोटाइप के लिए सुविधाजनक है जब एक अलग एडाप्टर वर्ग की आवश्यकता नहीं होती है। नकारात्मक पक्ष टाइप-सेफ टाइपिंग की कमी और कस्टम लॉजिक के साथ जटिलता है।
<!-- ListView के साथ लेआउट -->
<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>
कस्टम एडाप्टर ListView के लिए getView() विधि को ओवरराइड करता है, जिसे RecyclerView onCreateViewHolder + onBindViewHolder में विभाजित करता है। ListView में, दोनों चरण संयुक्त हैं, इसलिए डेवलपर को convertView (पुन: प्रयोज्य View) और setTag() विधि का उपयोग करके स्वतंत्र रूप से ViewHolder पैटर्न लागू करना होगा।
// डेटा मॉडल
data class Product(
name: String,
price: String,
imageResId: Int
)
// ViewHolder के साथ कस्टम एडाप्टर
class ProductAdapter(
context: Context,
private val products: List<Product>
) : ArrayAdapter<Product>(context, 0, products) {
// कैशिंग के लिए 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 से मुख्य अंतर: ListView में, getView() विधि हर बार कॉल की जाती है जब कोई आइटम स्क्रीन पर दिखाई देता है। यदि आप convertView और ViewHolder का उपयोग नहीं करते हैं, तो प्रत्येक स्क्रॉल एक नया View ऑब्जेक्ट बनाता है, जिससे मेमोरी लीक होती है और 50+ आइटम वाली सूचियों में अंतराल होता है। कस्टम लेआउट वाले ListView के लिए view.tag के साथ ViewHolder एक अनिवार्य अनुकूलन है।
ListView में चार आर्किटेक्चरल सीमाएँ हैं जिन्हें Google ने RecyclerView में ठीक किया: (1) केवल वर्टिकल ओरिएंटेशन — कोई ग्रिड, क्षैतिज सूचियाँ या स्टaggered लेआउट नहीं; (2) कोई विस्तृत सूचनाएँ नहीं — कोई भी डेटा परिवर्तन notifyDataSetChanged() के माध्यम से पूर्ण पुनर्चित्रण का कारण बनता है, जो झटके पैदा करता है; (3) आइटम जोड़ने/हटाने के लिए कोई अंतर्निहित एनिमेशन नहीं; (4) जिम्मेदारियों का कोई पृथक्करण नहीं — LayoutManager अंतर्निहित है, ItemAnimator अनुपस्थित है।
<!-- item_product.xml — ListView आइटम लेआउट -->
<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>
व्यावहारिक निहितार्थ: 20 आइटम तक की सूचियों पर, ListView RecyclerView जितनी तेज़ी से काम करता है। 100+ आइटम के साथ, अंतर ध्यान देने योग्य हो जाता है: ListView अंतर गणना और बलपूर्वक ViewHolder की कमी के कारण FPS गिराने लगता है। बार-बार अपडेट वाली सूचियों (चैट, फ़ीड, लॉग) के लिए, ListView उपयुक्त नहीं है — Paging 3 के साथ RecyclerView का उपयोग करें। IT Sectr में, हम 50 से अधिक आइटम वाली लीगेसी स्क्रीन पर काम करते समय ListView को RecyclerView में माइग्रेट करते हैं।
ListView बिना कोड के त्वरित कॉन्फ़िगरेशन के लिए XML विशेषताओं का एक सेट प्रदान करता है: android:divider (विभाजक का रंग/ड्रॉएबल), android:dividerHeight (मोटाई), android:scrollbars (स्क्रॉल बार), android:fastScrollEnabled (हैंडल के माध्यम से तेज़ स्क्रॉलिंग), android:choiceMode (चयन मोड: singleChoice, multipleChoice)। android:entries विशेषता बिना एडाप्टर के संसाधन ऐरे (string-array) से सूची भरने की अनुमति देती है।
| विशेषता | विवरण | उदाहरण मान |
|---|---|---|
| android:divider | विभाजक का रंग या ड्रॉएबल | @color/gray_light |
| android:dividerHeight | विभाजक की मोटाई px/dp में | 1dp |
| android:entries | संसाधनों से स्ट्रिंग ऐरे | @array/countries |
| android:choiceMode | आइटम चयन मोड | singleChoice |
| android:fastScrollEnabled | तेज़ स्क्रॉलिंग | true |
| android:overlapAnchor | पॉपअप सूचियों के लिए एंकर (API 21+) | true |
चयन मोड: choiceMode="singleChoice" RadioButton-शैली को सक्षम करता है जहाँ चयनित आइटम हाइलाइट किया जाता है। choiceMode="multipleChoice" — एकाधिक आइटम के लिए चेकबॉक्स। चयन डेटा listView.checkedItemPosition या listView.checkedItemIds के माध्यम से उपलब्ध है। महत्वपूर्ण: choiceMode का उपयोग करते समय, ListView पृष्ठभूमि के लिए StateListDrawable का उपयोग करता है — यदि डिफ़ॉल्ट नीला डिज़ाइन से मेल नहीं खाता है तो अपना स्वयं का सेलेक्टर सेट करें।
चयन ListView और RecyclerView के बीच प्रोजेक्ट आवश्यकताओं पर निर्भर करता है। RecyclerView आधुनिक मानक है, लेकिन ListView को लीगेसी कोड के लिए न्यूनतम रखरखाव लागत वाली सरल स्क्रीन के लिए उचित ठहराया जा सकता है। सभी प्रमुख मापदंडों पर तुलना:
| पैरामीटर | ListView | RecyclerView |
|---|---|---|
| लाइब्रेरी का आकार | SDK में अंतर्निहित (~60 KB) | AndroidX (~300 KB निर्भरताओं के साथ) |
| न्यूनतम संस्करण | API 1 | API 14 (AndroidX के माध्यम से) |
| ओरिएंटेशन | केवल वर्टिकल | वर्टिकल, क्षैतिज, ग्रिड, स्टaggered |
| ViewHolder | मैन्युअल कार्यान्वयन | आर्किटेक्चर द्वारा अनिवार्य |
| एनिमेशन | केवल फ़ेड ट्रांज़िशन | DefaultItemAnimator (add, remove, move, change) |
| विस्तृत अपडेट | नहीं (केवल notifyDataSetChanged) | notifyItemInserted/Removed/Changed |
| क्लिक लिसनर | onItemClickListener (अंतर्निहित) | ViewHolder के माध्यम से (अंतर्निहित नहीं) |
| प्रदर्शन | 50 आइटम तक की सूचियों के लिए पर्याप्त | 1000+ आइटम के लिए स्थिर 60 FPS |
निष्कर्ष: नई परियोजनाओं के लिए, RecyclerView का उपयोग करें। ListView को केवल लीगेसी कोड में रखें जहाँ माइग्रेशन अनावश्यक रूप से महँगा है। Material Design 3 (2026) दिशानिर्देशों के अनुसार, किसी भी जटिलता की सूचियों को आधुनिक प्रदर्शन और पहुँच मानकों को पूरा करने के लिए RecyclerView का उपयोग करना चाहिए।
अक्सर पूछे जाने वाले प्रश्न
ListView Android SDK API 35 में @Deprecated के रूप में चिह्नित नहीं है, लेकिन Google नई परियोजनाओं में इसका उपयोग करने की अनुशंसा नहीं करता है (soft-deprecated)। घटक Android के सभी संस्करणों में कार्यात्मक बना हुआ है। RecyclerView 2014 से आधिकारिक प्रतिस्थापन रहा है। यदि आप एक नया प्रोजेक्ट शुरू कर रहे हैं — RecyclerView चुनें। यदि आप किसी मौजूदा को बनाए रख रहे हैं — ListView बिना बदलाव के काम करता रहेगा।
ListView addHeaderView(View, Object, boolean) और addFooterView(View, Object, boolean) विधियों का समर्थन करता है। हेडर और फ़ुटर को आइटम की सामान्य सूची में जोड़ा जाता है लेकिन वे एडाप्टर में भाग नहीं लेते — वे हमेशा सूची की शुरुआत और अंत में प्रदर्शित होते हैं। महत्वपूर्ण: एडाप्टर सेट करने से पहले header/footer जोड़ें (setAdapter()), अन्यथा उन पर ध्यान नहीं दिया जाएगा। हेडर जोड़ने के बाद, आइटम स्थान ID हेडर की संख्या से स्थानांतरित हो जाती हैं।
ListView और ScrollView दोनों वर्टिकल जेस्चर को संभालते हैं, जो एक संघर्ष पैदा करता है: बाहरी ScrollView स्क्रॉलिंग को इंटरसेप्ट करता है, और ListView स्क्रॉल नहीं होता। समाधान: (1) ListView को ScrollView के अंदर नेस्ट न करें — NestedScrollingChild के साथ RecyclerView का उपयोग करें, (2) ScrollView को NestedScrollView (API 21+) से बदलें, (3) ScrollView के अंदर एक निश्चित ऊँचाई (android:layout_height="...dp") के साथ ListView का उपयोग करें, लेकिन यह रिस्पॉन्सिवनेस को तोड़ता है।
ListView में डेटा साफ़ करना एडाप्टर प्रकार पर निर्भर करता है। ArrayAdapter के लिए: adapter.clear() और adapter.addAll(newList) उसके बाद adapter.notifyDataSetChanged()। कस्टम एडाप्टर के लिए: डेटा सूची अपडेट करें और notifyDataSetChanged() कॉल करें। नोट: listView.invalidateViews() केवल Views को पुनर्चित्रित करता है लेकिन डेटा अपडेट नहीं करता। हमेशा एडाप्टर के माध्यम से डेटा बदलें, सीधे नहीं।
ListView आइटम की ऊँचाई आइटम लेआउट XML में सेट की जाती है। यदि लेआउट layout_height="wrap_content" का उपयोग करता है, तो ऊँचाई सामग्री के अनुसार समायोजित हो जाती है। सभी आइटम की एक निश्चित ऊँचाई के लिए, एक कस्टम एडाप्टर का उपयोग करें जो getView() में LayoutParams सेट करता है: view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight)। विभिन्न ऊँचाइयों के लिए, विभिन्न व्यू प्रकारों के साथ RecyclerView का उपयोग करें।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें