RecyclerView — komponen Android Jetpack untuk menampilkan kumpulan data besar secara efisien dalam bentuk daftar dan grid. Tidak seperti ListView, RecyclerView menggunakan kembali ViewHolder dan mengelola tata letak melalui LayoutManager. Menurut Google (Android Developers, 2026), RecyclerView memproses hingga 60 frame per detik saat menggulir daftar dengan 1000+ elemen berkat kumpulan ViewHolder dan algoritma perbedaan DiffUtil. Baca lebih lanjut tentang arsitektur aplikasi Android di artikel kami tentang ListView.
Utama
RecyclerView — komponen pustaka Android Jetpack, diperkenalkan di Google I/O 2014 sebagai bagian dari Android Support Library v7. Ini dirancang untuk menampilkan daftar dan grid dinamis dengan kinerja tinggi. RecyclerView muncul sebagai pengganti ListView dan memecahkan masalah utama pendahulunya — kurangnya penggunaan kembali ViewHolder secara paksa.
Arsitektur RecyclerView dibangun di atas pola Model-View-Adapter: data disimpan dalam model (List, LiveData, Flow), tampilan dikelola oleh Adapter, dan tata letak dikendalikan oleh LayoutManager. Setiap komponen bertanggung jawab atas area tanggung jawabnya sendiri, membuat sistem fleksibel dan dapat diperluas.
Menurut survei Android Developers (2025), RecyclerView digunakan di 78% aplikasi Android dari top-100 Google Play. Kinerja pengguliran daftar dengan 1000+ elemen tetap stabil pada 60 FPS di perangkat kelas menengah berkat tiga mekanisme: kumpulan ViewHolder, perhitungan perbedaan pembaruan, dan pemuatan data asinkron.
RecyclerView optimal untuk: daftar dengan jumlah elemen tidak diketahui (feed, chat, log), grid dengan N kolom (galeri, katalog), tata letak kaskade (papan Pinterest), daftar dengan animasi penambahan/penghapusan elemen. Untuk layar sederhana dengan 2-5 elemen, LinearLayout atau ScrollView lebih sederhana dan efisien — RecyclerView menambah overhead.
Untuk menggunakan RecyclerView, tambahkan dependensi di build.gradle (app): implementation 'androidx.recyclerview:recyclerview:1.4.0'. Versi API minimum — 14 (Android 4.0). Mulai AndroidX RecyclerView 1.3.0, tersedia modul recyclerview-selection untuk pemilihan elemen dan recyclerview-swipe untuk gesekan.
RecyclerView dibagi menjadi tiga lapisan independen: Adapter mengelola data dan ViewHolder, LayoutManager bertanggung jawab untuk memposisikan elemen, ItemAnimator mengontrol animasi. Arsitektur semacam itu memungkinkan penggantian lapisan mana pun tanpa mengubah yang lain — misalnya, beralih dari LinearLayoutManager ke GridLayoutManager tanpa mengubah kode Adapter.
| Komponen | Tanggung Jawab | Implementasi |
|---|---|---|
| Adapter | Membuat ViewHolder, mengikat data ke View, memberi tahu perubahan | RecyclerView.Adapter<VH> |
| ViewHolder | Menyimpan cache referensi ke View, menghindari findViewById() | RecyclerView.ViewHolder |
| LayoutManager | Memposisikan elemen, menentukan arah gulir | LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager |
| ItemAnimator | Animasi penambahan, penghapusan, pemindahan elemen | DefaultItemAnimator |
| ItemDecoration | Menggambar pemisah, spasi, latar belakang antar elemen | RecyclerView.ItemDecoration |
Siklus kerja: (1) Adapter membuat ViewHolder melalui onCreateViewHolder(), (2) LayoutManager menentukan posisi View baru di layar, (3) Adapter mengikat data melalui onBindViewHolder(), (4) saat menggulir, ViewHolder yang keluar layar masuk ke kumpulan (RecycledViewPool) untuk digunakan kembali. Alih-alih membuat View baru, yang sudah ada digunakan kembali — ini adalah mekanisme kinerja utama.
ViewHolder — kelas yang menyimpan referensi ke View (TextView, ImageView, dll.) di dalam elemen daftar. Tanpa ViewHolder, setiap kali menggulir sistem akan memanggil findViewById() — salah satu operasi termahal di Android UI. ViewHolder menghilangkan panggilan ini dengan mengingat referensi setelah pengikatan pertama.
// Model data
data class Article(
title: String,
summary: String,
author: String,
imageUrl: String?
)
// ViewHolder — menyimpan referensi ke View
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
}
}
Aturan praktis: setiap View dalam tata letak item harus dideklarasikan sebagai properti ViewHolder dengan findViewById() tepat satu kali — di konstruktor. Metode bind() tidak memanggil findViewById(), hanya mengatur teks, warna, dan pendengar. Pendekatan ini mempercepat pengguliran daftar sebesar 30-50% menurut Google (Android Performance Patterns, 2025).
LayoutManager menentukan bagaimana elemen ditempatkan di dalam RecyclerView. Secara default, Android menyediakan tiga implementasi: LinearLayoutManager, GridLayoutManager, dan StaggeredGridLayoutManager. Pilihan LayoutManager memengaruhi persepsi data oleh pengguna dan kinerja pengguliran.
| LayoutManager | Tata Letak | Kapan Digunakan | Metode Pengaturan |
|---|---|---|---|
| LinearLayoutManager | Daftar (vertikal atau horizontal) | Feed, chat, notifikasi, daftar produk | LinearLayoutManager(context) |
| GridLayoutManager | Grid dengan N kolom | Galeri, katalog, ikon, grid gambar | GridLayoutManager(context, spanCount) |
| StaggeredGridLayoutManager | Grid kaskade (tinggi elemen berbeda) | Papan Pinterest, catatan, galeri masonry | StaggeredGridLayoutManager(spanCount, orientation) |
// Mengatur LinearLayoutManager di Fragment
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)
// Optimasi: ukuran tetap + kumpulan
recyclerView.setHasFixedSize(true)
recyclerView.setItemViewCacheSize(20)
// Pemisah antar elemen
val divider = DividerItemDecoration(requireContext(), LinearLayoutManager.VERTICAL)
recyclerView.addItemDecoration(divider)
}
}
Kinerja: LinearLayoutManager dengan guliran vertikal adalah opsi tercepat, karena elemen ditempatkan secara berurutan dan LayoutManager menghitung posisi dalam O(1). GridLayoutManager memerlukan perhitungan tambahan untuk pembagian kolom, tetapi tetap efisien dengan spanCount tetap. StaggeredGridLayoutManager adalah yang paling lambat dari ketiganya, karena harus menghitung posisi elemen dalam kaskade dengan mempertimbangkan tinggi elemen tetangga. Gunakan hanya ketika tinggi sel yang berbeda diperlukan secara visual.
Adapter di RecyclerView mengimplementasikan pola Adapter dari GoF: mengubah data (List<T>) menjadi ViewHolder yang ditampilkan di layar. Saat data berubah, Adapter dapat memberi tahu RecyclerView melalui metode notifyDataSetChanged(), notifyItemInserted(), dan sejenisnya. Masalahnya adalah notifyDataSetChanged() menggambar ulang semua elemen yang terlihat, yang menyebabkan sentakan (jank).
// Adapter dengan DiffUtil untuk pembaruan efisien
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
// Pembaruan daftar melalui DiffUtil
fun updateArticles(newArticles: List<Article>) {
val diffCallback = ArticleDiffCallback(articles, newArticles)
val diffResult = DiffUtil.calculateDiff(diffCallback)
articles = newArticles
diffResult.dispatchUpdatesTo(this)
}
}
// Callback untuk DiffUtil
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 menggunakan algoritma perbedaan Eugene W. Myers, yang menghitung jumlah minimum operasi (insert, remove, move, change) untuk mengubah daftar lama menjadi baru. Untuk daftar 100 elemen, DiffUtil bekerja dalam 1-5 ms (Google, 2025). Untuk daftar besar (10000+), gunakan AsyncListDiffer atau PagingDataAdapter dari pustaka Paging — mereka melakukan perhitungan di latar belakang.
ListView — pendahulu RecyclerView, muncul di Android 1.0 (API 1). Ia juga menampilkan daftar, tetapi tidak mewajibkan ViewHolder, tidak mendukung LayoutManager, dan tidak dapat menganimasikan perubahan. RecyclerView dirancang sebagai pengganti ListView dengan arsitektur yang lebih ketat dan kinerja yang lebih baik.
| Kriteria | RecyclerView | ListView |
|---|---|---|
| ViewHolder | Wajib (arsitektur) | Disarankan, tetapi tidak wajib |
| LayoutManager | Pembagian: daftar, grid, kaskade | Hanya daftar vertikal |
| Animasi perubahan | DefaultItemAnimator langsung | Tidak ada dukungan bawaan |
| Pemberitahuan perubahan | Titik: notifyItemInserted/Removed | notifyDataSetChanged() hanya seluruh daftar |
| DiffUtil | Dukungan melalui DiffUtil.Callback | Tidak ada padanan |
| Pemisah | ItemDecoration (kustom) | android:divider (bawaan) |
| Versi minimum | API 14 (Android 4.0) melalui AndroidX | API 1 (semua versi) |
Rekomendasi Google (Android Developers, 2026): gunakan RecyclerView untuk semua proyek baru. ListView dapat dipertahankan di basis kode lama (legacy) di mana migrasi tidak sepadan dengan biayanya. RecyclerView memberikan kinerja lebih baik pada 100+ elemen, mendukung guliran horizontal dan grid tanpa solusi tambahan. Di Android 15, ListView secara resmi ditandai sebagai sebagian tidak digunakan lagi.
Pertanyaan yang Sering Diajukan
Periksa tiga kondisi: (1) Adapter diatur melalui recyclerView.adapter = adapter, (2) LayoutManager diatur melalui recyclerView.layoutManager = LinearLayoutManager(context), (3) data dalam daftar tidak kosong dan adapter telah diberi tahu (notifyDataSetChanged()). Kesalahan umum — mengatur data setelah memanggil notifyDataSetChanged(). Data harus ditetapkan sebelum pemberitahuan. Periksa ukuran daftar: adapter.itemCount harus lebih besar dari 0.
Kelambatan saat menggulir (jank) terjadi ketika onBindViewHolder() melakukan operasi berat: memuat gambar tanpa cache, findViewById() di dalam bind, perhitungan kompleks. Solusi: (1) gunakan pustaka Glide atau Coil untuk pemuatan gambar asinkron, (2) pindahkan semua findViewById() ke konstruktor ViewHolder, (3) untuk perhitungan perbedaan gunakan AsyncListDiffer. Aktifkan pembuatan profil GPU di Android Studio (Profile GPU Rendering) untuk menemukan bingkai lambat.
Berikan orientasi ke LayoutManager: LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false). Parameter kedua adalah reverseLayout (false = kiri ke kanan). Untuk grid horizontal, gunakan GridLayoutManager dengan orientasi horizontal atau LinearSnapHelper kustom untuk guliran per halaman. Daftar horizontal cocok untuk karosel produk, gambar, kategori.
RecyclerView tidak memiliki onClickListener bawaan (tidak seperti ListView dengan onItemClickListener). Implementasikan di ViewHolder: berikan lambda ke konstruktor dan atur itemView.setOnClickListener. Contoh: class ArticleViewHolder(itemView: View, val onItemClick: (Article) -> Unit) : RecyclerView.ViewHolder(itemView). Panggil onItemClick(article) di dalam bind(). Alternatif — atur RecyclerView.addOnItemTouchListener() untuk menangani gestur.
RecycledViewPool — kumpulan internal ViewHolder yang menjadi tidak terlihat saat menggulir. Alih-alih dihancurkan, mereka disimpan di kumpulan dan digunakan kembali. Secara default, kumpulan menyimpan 5 ViewHolder dari setiap jenis. Tingkatkan ukuran untuk tata letak kompleks: recyclerView.getRecycledViewPool().setMaxRecycledViews(VIEW_TYPE_NORMAL, maxCount). Jika RecyclerView memiliki beberapa jenis View (viewType), kumpulan menyimpan tumpukan terpisah untuk masing-masing. Berbagi RecycledViewPool antara RecyclerView yang berbeda menghemat memori di layar dengan daftar bersarang.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga