ListView — pangunahing Android component para sa pagpapakita ng mga vertical na listahan, available mula API 1 (Android 1.0). Gumagawa ang ListView ng listahan mula sa mga elemento gamit ang ArrayAdapter at sumusuporta sa custom na cell layout. Alamin kung ano ang ListView, paano ito i-configure, at anong mga pitfalls ang tinatago ng luma ngunit ginagamit pa ring component na ito. Sa IT Sectr nakakasalubong namin ang ListView sa legacy-proyekto at sinusuportahan ang backward compatibility sa Android 4.4. Para sa paghahambing sa modernong alternatibo basahin ang artikulo tungkol sa RecyclerView.
Mga Pangunahing
ListView — ay isang View group mula sa package na android.widget, na idinisenyo para sa pagpapakita ng naka-scroll na listahan ng mga elemento. Ini-implement ng ListView ang pattern na AdapterView: ang data ay ipinapasa sa pamamagitan ng adapter (Adapter), na nagco-convert ng data elements sa View na ipinapakita sa screen. Ang ListView ay nasa Android SDK mula pa sa unang bersyon (API 1) at hindi nangangailangan ng karagdagang library.
Arkitektura ng ListView ay mas simple kaysa RecyclerView: LayoutManager ay built-in (vertical scroll lang), walang animation ng pagbabago, ang mga divider ay nakatakda sa pamamagitan ng XML attribute na android:divider. Awtomatikong nagdadagdag ang ListView ng OverScrollView at pag-highlight sa focus, na nagpapasimple ng prototyping. Ayon sa datos ng Statista (2025), humigit-kumulang 15% ng Android apps sa top-100 Play Store ay naglalaman pa rin ng ListView — pangunahin ang legacy-proyekto na may minimal na suporta.
Ang ListView ay ang pangunahing component ng listahan sa Android mula 2008 hanggang 2014, nang ipakilala ang RecyclerView sa Google I/O 2014. Sa kabila ng status na bahagyang luma (soft-deprecated), nananatiling available ang ListView sa lahat ng bersyon ng Android at hindi minarkahan bilang @Deprecated sa SDK API 35. Kung ang iyong proyekto ay sumusuporta sa Android 4.4 (API 19) at mas mababa, ang ListView ay ang tanging built-in na pagpipilian, dahil ang RecyclerView ay nangangailangan ng AndroidX at gradle dependencies.
ArrayAdapter — ang pinakasikat na adapter para sa ListView. Tumatanggap ito ng List<T> at layout para sa bawat elemento. Bilang default, tinatawagan ng ArrayAdapter ang toString() para sa bawat object at ipinapakita ang text sa simple_list_item_1 (isang TextView). Para sa custom na pagpapakita kailangang i-override ang getView() o magpasa ng custom na layout sa constructor.
// ListView na may ArrayAdapter (simpleng text)
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val countries = listOf(
"Russia", "USA", "Germany",
"France", "Japan", "China", "Brazil"
)
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
// Paghawak ng click
binding.listView.onItemClickListener =
AdapterView.OnItemClickListener { _, _, position, _ ->
Toast.makeText(this, countries[position], Toast.LENGTH_SHORT).show()
}
}
}
SimpleAdapter ay para sa mga listahan mula sa Map-data. Tumatanggap ito ng List<Map<String, Any>> at array na from/to para sa pagbind ng Map keys sa ID ng widgets sa layout. Ang SimpleAdapter ay maginhawa para sa mabilis na prototype kapag hindi kailangan ang hiwalay na adapter class. Disbentahe — kawalan ng type-safe typing at kahirapan sa custom na logic.
<!-- Layout na may 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>
Custom na adapter para sa ListView ay nag-o-override ng method na getView(), na hinahati ng RecyclerView sa onCreateViewHolder + onBindViewHolder. Sa ListView ang parehong hakbang ay pinagsama, kaya ang developer ay dapat mag-implement ng pattern na ViewHolder nang nakapag-iisa sa pamamagitan ng convertView (reusable na View) at tag na setTag().
// Modelo ng data
data class Product(
name: String,
price: String,
imageResId: Int
)
// Custom na adapter na may ViewHolder
class ProductAdapter(
context: Context,
private val products: List<Product>
) : ArrayAdapter<Product>(context, 0, products) {
// ViewHolder para sa caching
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
}
}
Pangunahing pagkakaiba sa RecyclerView: sa ListView ang method na getView() ay tinatawagan para sa bawat paglitaw ng elemento sa screen. Kung hindi ginagamit ang convertView at ViewHolder, bawat scroll ay lumilikha ng bagong View object, na nagreresulta sa memory leak at lag sa mga listahan na may 50+ elemento. ViewHolder na may view.tag — sapilitang optimization para sa ListView na may custom na layout.
ListView ay may apat na architectural na limitasyon na inayos ng Google sa RecyclerView: (1) vertical orientation lang — walang grids, horizontal na listahan, o cascades; (2) kawalan ng point notification — anumang pagbabago sa data ay nagdudulot ng kumpletong pag-redraw sa pamamagitan ng notifyDataSetChanged(), na lumilikha ng jerking; (3) walang built-in na animation ng pagdagdag/pag-alis ng elemento; (4) walang paghihiwalay ng responsibilidad — LayoutManager ay built-in, ItemAnimator ay wala.
<!-- item_product.xml — layout ng elemento ng 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>
Praktikal na kahihinatnan: sa listahan hanggang 20 elemento, ang ListView ay gumagana nang kasing bilis ng RecyclerView. Sa 100+ elemento, ang pagkakaiba ay nagiging kapansin-pansin: ang ListView ay nagsisimulang mawalan ng FPS dahil sa kawalan ng differential calculations at sapilitang ViewHolder. Para sa mga listahan na may madalas na pag-update (chat, feed, log) ang ListView ay hindi angkop — gamitin ang RecyclerView na may Paging 3. Sa IT Sectr, mina-migrate namin ang ListView sa RecyclerView sa bawat trabaho sa legacy screen na may higit sa 50 elemento.
ListView ay nagbibigay ng set ng XML attributes para sa mabilis na pag-configure nang walang code: android:divider (kulay/drawing ng divider), android:dividerHeight (kapal), android:scrollbars (scroll bars), android:fastScrollEnabled (mabilis na scroll sa pamamagitan ng handle), android:choiceMode (mode ng pagpili: singleChoice, multipleChoice). Ang attribute na android:entries ay nagpapahintulot na punan ang listahan mula sa resource array (string-array) nang walang adapter.
| Attribute | Paglalarawan | Halimbawang Halaga |
|---|---|---|
| android:divider | Kulay o drawable ng divider | @color/gray_light |
| android:dividerHeight | Kapal ng divider sa px/dp | 1dp |
| android:entries | Array ng strings mula sa resources | @array/countries |
| android:choiceMode | Mode ng pagpili ng elemento | singleChoice |
| android:fastScrollEnabled | Mabilis na scroll | true |
| android:overlapAnchor | Anchor para sa popup listahan (API 21+) | true |
Mode ng pagpili: choiceMode="singleChoice" ay nag-a-activate ng RadioButton style, kung saan ang napiling elemento ay naka-highlight. choiceMode="multipleChoice" — checkbox para sa maraming elemento. Ang data ng pagpili ay available sa pamamagitan ng listView.checkedItemPosition o listView.checkedItemIds. Mahalaga: sa choiceMode ang ListView ay gumagamit ng StateListDrawable para sa background — mag-set ng sarili mong selector kung ang default na asul ay hindi tugma sa disenyo.
Pagpipilian sa pagitan ng ListView at RecyclerView ay depende sa mga kinakailangan ng proyekto. Ang RecyclerView ay modernong standard, ngunit ang ListView ay maaaring maging makatwiran para sa simpleng screen na may minimal na gastos sa pagpapanatili ng lumang code. Paghahambing ayon sa lahat ng key parameter:
| Parameter | ListView | RecyclerView |
|---|---|---|
| Laki ng Library | Built-in sa SDK (≈60 KB) | AndroidX (≈300 KB na may dependencies) |
| Pinakamababang Bersyon | API 1 | API 14 (sa pamamagitan ng AndroidX) |
| Orientasyon | Vertical lang | Vertical, horizontal, grid, cascade |
| ViewHolder | Manual na implementasyon | Sapilitan ayon sa arkitektura |
| Animasyon | Fade transition lang | DefaultItemAnimator (add, remove, move, change) |
| Point Updates | Wala (notifyDataSetChanged lang) | notifyItemInserted/Removed/Changed |
| Click listener | onItemClickListener (built-in) | Sa pamamagitan ng ViewHolder (walang built-in) |
| Performance | Sapat para sa listahan hanggang 50 elemento | Stable na 60 FPS para sa 1000+ elemento |
Konklusyon: para sa bagong proyekto gamitin ang RecyclerView. Iwanan ang ListView lamang sa legacy code kung saan ang migration ay hindi makatwirang mahal. Ayon sa mga guideline ng Material Design 3 (2026), ang mga listahan ng anumang kumplikasyon ay dapat gumamit ng RecyclerView upang matugunan ang mga modernong standard ng performance at accessibility.
Mga Madalas Itanong
ListView ay hindi minarkahan bilang @Deprecated sa Android SDK API 35, ngunit hindi inirerekomenda ng Google ang paggamit nito sa mga bagong proyekto (soft-deprecated). Ang component ay nananatiling gumagana sa lahat ng bersyon ng Android. Ang RecyclerView ay opisyal na kapalit mula 2014. Kung magsisimula ka ng bagong proyekto — piliin ang RecyclerView. Kung nagpapanatili ka ng umiiral na — ang ListView ay patuloy na gagana nang walang pagbabago.
Ang ListView ay sumusuporta sa mga method na addHeaderView(View, Object, boolean) at addFooterView(View, Object, boolean). Ang header at footer ay idinaragdag sa pangkalahatang listahan ng mga elemento, ngunit hindi lumalahok sa adapter — palagi silang ipinapakita sa simula at dulo ng listahan. Mahalaga: idagdag ang header/footer bago itakda ang adapter (setAdapter()), kung hindi ay hindi sila isasaalang-alang. Pagkatapos magdagdag ng header, ang ID ng mga posisyon ng elemento ay lumilipat ng bilang ng mga header.
ListView at ScrollView parehong nagpoproseso ng vertical gestures, na lumilikha ng conflict: ang panlabas na ScrollView ay humaharang sa scroll, at ang ListView ay hindi nag-scroll. Solusyon: (1) huwag ilagay ang ListView sa loob ng ScrollView — gamitin ang RecyclerView na may NestedScrollingChild, (2) palitan ang ScrollView ng NestedScrollView (API 21+), (3) gamitin ang ListView na may fixed height (android:layout_height="...dp") sa loob ng ScrollView, ngunit sisirain nito ang adaptability.
Ang pag-clear ng data sa ListView ay depende sa uri ng adapter. Para sa ArrayAdapter: adapter.clear() at adapter.addAll(newList) na sinusundan ng adapter.notifyDataSetChanged(). Para sa custom na adapter: i-update ang listahan ng data at tawagan ang notifyDataSetChanged(). Paalala: listView.invalidateViews() ay nagre-redraw lang ng View, ngunit hindi nag-u-update ng data. Palaging baguhin ang data sa pamamagitan ng adapter, hindi direkta.
Ang taas ng elemento ng ListView ay itinakda sa item layout. Kung ang layout ay gumagamit ng layout_height="wrap_content", ang taas ay umaayon sa nilalaman. Para sa fixed height ng lahat ng elemento gamitin ang custom na adapter na nagtatakda ng LayoutParams sa getView(): view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight). Para sa iba't ibang taas gamitin ang RecyclerView na may iba't ibang view types.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din