Menampilkan Daftar
Data
Dinamis 📜
Pernah penasaran bagaimana Instagram atau TikTok bisa men-scroll ribuan postingan tanpa bikin HP-mu hang atau crash? Rahasianya ada di teknik daur ulang memori: RecyclerView!
1. Kenapa Nggak Pakai ScrollView Biasa?
Bayangkan kamu punya aplikasi kontak dengan 10.000 nama. Kalau kamu pakai
ScrollView dan LinearLayout biasa, Android akan menggambar
(nge-render) ke-10.000 nama itu secara bersamaan ke dalam memori RAM, walaupun yang
kelihatan di layar cuma 5 nama!
Hasilnya? OOM (Out of Memory). Aplikasimu langsung Force Close!
Solusinya: Konsep Daur Ulang
RecyclerView bekerja cerdas. Dia hanya memuat elemen yang terlihat di layar + beberapa cadangan di baliknya. Saat kamu nge-scroll ke bawah, elemen yang sudah lewat di atas akan dilepas, dibersihkan datanya, lalu dipindah ke bawah untuk digunakan oleh data baru! Memori yang terpakai tetap stabil.
Simulasi Recycling Element
2. Lima Pilar (Anatomi RecyclerView)
1. Model Data
Bahan bakunya. Biasanya berupa ArrayList
berisi Class Object Java (Contoh: Kumpulan data Kopi yang berisi Nama,
Harga, Foto).
2. Item Layout (XML)
File XML terpisah khusus untuk mendesain SATU BARIS item saja (cetakan desainnya). Nanti desain ini akan di-copy-paste otomatis oleh sistem.
3. RecyclerView (UI)
Komponen kosong yang ditaruh di
activity_main.xml. Dia hanya bertugas sebagai wadah (container) tempat list-nya
akan ditampilkan.
4. Layout Manager
Sang Mandor. Mengatur apakah barisan item tadi mau disusun lurus ke bawah (Linear), ke samping, atau kotak-kotak (Grid).
5. Adapter & ViewHolder (The Core)
Ini dia si pekerja keras (File Java). ViewHolder bertugas mencari ID komponen XML (findViewById), sedangkan Adapter adalah perantaranya. Dialah yang mengambil Data dari sumber, lalu memasukkannya satu-satu ke dalam cetakan ViewHolder secara berulang-ulang.
3. Simulator LayoutManager
Kekuatan LayoutManager
Hebatnya RecyclerView, kita tidak perlu mengubah desain item-nya. Cukup ubah LayoutManager-nya, maka wujud aplikasimu akan berubah total! Coba klik mode di bawah ini:
rvKopi.setLayoutManager(new LinearLayoutManager(this));
Menu Minuman
4. Alur Kerja & View Lifecycle
A. Bagaimana 5 File Tersebut Bekerja Sama?
Jangan bingung dengan banyaknya file. Pahami saja alur sederhananya seperti sebuah pabrik perakitan mobil:
B. Apakah Ada Kaitannya dengan Android Lifecycle?
Tentu saja! Tapi bukan Activity Lifecycle, melainkan View Lifecycle di dalam Adapter. Proses ini dirancang untuk sangat menghemat RAM dan Baterai.
1. onCreateViewHolder()
Proses Berat:
Mirip dengan onCreate() di Activity. Di sinilah Android membedah file XML
menjadi objek nyata (Inflate).
Efisiensinya: Sistem HANYA akan memanggil
fungsi ini beberapa kali di awal (misalnya 7 kali jika layarmu hanya muat 5 item + 2
cadangan). Setelah itu, fungsi ini tidak akan pernah dipanggil lagi meski kamu
nge-scroll 10.000 data!
2. onBindViewHolder()
Proses Ringan:
Mirip dengan onResume(). Di sinilah tugas mengganti teks dan foto
terjadi.
Efisiensinya: Saat kamu nge-scroll bawah, item yang menghilang di
atas akan masuk ke Recycle Pool (bukan dibunuh/destroy). Sistem mengambil
cetakan kosong itu, lalu HANYA memanggil onBindViewHolder() untuk
mengganti isi teksnya dengan data yang baru. Sangat cepat!
5. Bedah Kode (The Core)
Membuat RecyclerView memang butuh persiapan banyak file. Supaya tidak tersesat, ikuti urutan tab di bawah ini dari kiri ke kanan saat coding di Android Studio!
Info File: activity_main.xml
Layar (Wadah) Utama Aplikasi.
Tempat menaruh
komponen RecyclerView kosong (sebagai etalase) yang siap diisi
daftar data.
Otomatis ada saat kamu membikin Project baru (Empty Views Activity).
<!-- activity_main.xml (Wadah Utama) -->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Pasang komponen RecyclerView. Biarkan kosong, dia akan diisi dari Java nanti! -->
<!-- Praktik Terbaik ConstraintLayout: Gunakan 0dp dan ikat 4 sisinya! -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvKopi"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Info File: item_row.xml
Desain satu baris item.
Menentukan letak foto, judul, dan harga. Ibarat "Cetakan Kue", desain ini akan difotokopi berulang kali ke bawah.
Klik kanan
folder res/layout
➔ New ➔ Layout Resource File ➔
ketik nama item_row.
layout_height diatur ke wrap_content
agar 1 baris item tidak melar memakan tinggi seisi layar HP!
<!-- item_row.xml (Desain untuk 1 baris) -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" <!-- WAJIB wrap_content! -->
android:orientation="horizontal"
android:padding="16dp"
android:layout_marginBottom="8dp">
<ImageView
android:id="@+id/imgFoto"
android:layout_width="80dp"
android:layout_height="80dp"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="16dp">
<TextView
android:id="@+id/tvNamaKopi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="18sp" />
<TextView
android:id="@+id/tvHarga"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#0d9488" />
</LinearLayout>
</LinearLayout>
Info File: Kopi.java (Model OOP)
Model Data (Blueprint).
Membungkus data (Nama Kopi, Harga, Foto) menjadi 1 objek utuh agar rapi saat dimasukkan ke dalam keranjang (List).
Klik kanan
folder package Java
➔ New ➔ Java Class ➔ beri nama
Kopi.
package com.example.recyclerviewapp;
// Model Data (Class Java biasa tanpa extends)
public class Kopi {
private String nama;
private String harga;
private int fotoResId; // Tipe INT karena merujuk ke id R.drawable.nama_foto
// Constructor (Fungsi untuk memasukkan data ke kotak)
public Kopi(String nama, String harga, int fotoResId) {
this.nama = nama;
this.harga = harga;
this.fotoResId = fotoResId;
}
// Getter (Fungsi untuk mengambil kembali datanya)
public String getNama() { return nama; }
public String getHarga() { return harga; }
public int getFotoResId() { return fotoResId; }
}
Info File: KopiAdapter.java (Pekerja Keras)
Mesin perakit list (Adapter).
Ini yang
melakukan proses Daur Ulang. Ia mengambil data utuh dari Kopi.java,
lalu menempelkannya ke desain item_row.xml.
Bikin Java
Class bernama KopiAdapter ➔ lalu ketik
extends RecyclerView.Adapter ➔ klik lampu merah (Alt+Enter).
package com.example.recyclerviewapp;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
// Class Adapter wajib meng-extends RecyclerView.Adapter
public class KopiAdapter extends RecyclerView.Adapter<KopiAdapter.KopiViewHolder> {
private ArrayList<Kopi> listKopi;
// Konstruktor (Menerima ember berisi tumpukan data dari MainActivity)
public KopiAdapter(ArrayList<Kopi> list) {
this.listKopi = list;
}
// TAHAP 1 (Proses Berat): Membuat cetakan bungkus kosong (Memfotokopi item_row.xml)
// Dipanggil hanya beberapa kali oleh sistem Android.
@NonNull
@Override
public KopiViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, parent, false);
return new KopiViewHolder(view);
}
// TAHAP 2 (Proses Ringan): Mengisi data ke dalam cetakan yang sudah dibuat
// Dipanggil terus-menerus setiap kali kamu nge-scroll layar.
@Override
public void onBindViewHolder(@NonNull KopiViewHolder holder, int position) {
Kopi kopi = listKopi.get(position); // Ambil data urutan ke-N
holder.tvNama.setText(kopi.getNama()); // Tempel ke TextView
holder.tvHarga.setText(kopi.getHarga());
holder.imgFoto.setImageResource(kopi.getFotoResId());
}
// TAHAP 3: Beri tahu sistem berapa total data yang ada di dalam keranjang
@Override
public int getItemCount() {
return listKopi.size();
}
// ========================================================
// SUB-CLASS VIEWHOLDER (Tukang cari ID Komponen di dalam item_row.xml)
public class KopiViewHolder extends RecyclerView.ViewHolder {
TextView tvNama, tvHarga;
ImageView imgFoto;
public KopiViewHolder(@NonNull View itemView) {
super(itemView);
// Wajib pakai itemView.findViewById karena komponennya ada di file xml lain
tvNama = itemView.findViewById(R.id.tvNamaKopi);
tvHarga = itemView.findViewById(R.id.tvHarga);
imgFoto = itemView.findViewById(R.id.imgFoto);
}
}
}
Info File: MainActivity.java (Pusat Komando)
Pusat Komando (Main Controller).
Membuat dummy data, memilih LayoutManager (memanjang atau grid), lalu menyuruh Adapter untuk mulai bekerja merakitnya di layar.
Otomatis
terbuat. Tinggal tambahkan kodenya di dalam blok fungsi onCreate().
Teks
R.drawable.ic_kopi1
di bawah ini akan error (bergaris merah) jika kamu BELUM meletakkan file
gambar bernama ic_kopi1.png/jpg ke dalam folder
res/drawable di Android Studio! Jika dipaksa Run saat gambar tidak ada,
aplikasimu akan CRASH / Force Close (ResourceNotFoundException).
package com.example.recyclerviewapp;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private RecyclerView rvKopi;
private ArrayList<Kopi> listData = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvKopi = findViewById(R.id.rvKopi);
// 1. Siapkan Datanya (Menambah 4 objek Kopi ke dalam ArrayList)
// PASTIKAN GAMBAR SUDAH ADA DI FOLDER DRAWABLE SEBELUM MENGETIK KODE INI!
listData.add(new Kopi("Kopi Hitam", "Rp 15.000", R.drawable.ic_kopi1));
listData.add(new Kopi("Cappuccino", "Rp 25.000", R.drawable.ic_kopi2));
listData.add(new Kopi("Matcha Latte", "Rp 30.000", R.drawable.ic_kopi3));
listData.add(new Kopi("Red Velvet", "Rp 28.000", R.drawable.ic_kopi4));
// 2. Atur LayoutManager (Wajib! Agar tahu mau disusun vertikal atau grid)
rvKopi.setLayoutManager(new LinearLayoutManager(this));
// 3. Panggil pekerja keras kita (Adapter), serahkan datanya, lalu pasang ke RecyclerView
KopiAdapter adapter = new KopiAdapter(listData);
rvKopi.setAdapter(adapter);
}
}
6. Spill Dunia Kerja: Narik Data API
Kalo Datanya Ada 10.000 Biji, Masa Diketik Manual?
Di modul ini kita memang ngetik manual pakai listData.add(...) buat latihan.
Tapi tenang aja, di dunia kerja (kayak pas kamu bikin Tokopedia atau Gojek), ribuan data itu
ditarik otomatis dari Server/Internet dalam bentuk JSON!
Namun, Android punya Aturan Main super ketat soal internet. Biar nggak bingung, mari
kita kenalan dulu dengan istilah-istilah wajib di bawah ini:
A. Kenalan Sama Istilahnya Dulu 🤝
1. Apa itu UI Thread?
Analogi: KASIR TOKO.
UI Thread (Main Thread) adalah jalur utama aplikasi. Tugasnya Kasir cuma
satu: nyapa pelanggan, nampilin tombol, dan nerima ketikan/klik. Kasir harus selalu
senyum (responsif).
2. Background Thread?
Analogi: PEGAWAI GUDANG.
Jalur belakang layar. Segala hal yang berat (narik data internet, ngolah database,
download foto 100MB) WAJIB diserahkan ke Pegawai Gudang, biar Kasir di depan
nggak kelabakan ngelayanin user.
3. Retrofit & Volley?
Analogi: JASA KURIR (GoSend/J&T).
Ini adalah Library (Pustaka Pihak Ketiga). Daripada nulis kode Background
Thread manual yang pusing, kita mending "menyewa" jasa kurir. Kita tinggal
kasih URL API-nya, si Retrofit bakal ngurusin koneksinya otomatis!
B. Tiga Aturan Ketat Android ⚠️
1. Wajib Izin Internet
Aplikasi akan langsung ditolak sistem
jika kamu lupa menambahkan baris kode <uses-permission...>
di dalam file AndroidManifest.xml.
2. Haram di UI Thread
Kamu TIDAK BOLEH mendownload data internet di jalur utama aplikasi (UI Thread) karena akan membuat HP hang/freeze dan memicu error NetworkOnMainThreadException. Wajib pakai Background Thread / Library!
3. Notify Data Changed
Setelah data dari internet berhasil
ditangkap dan dimasukkan ke `ArrayList`, kamu WAJIB melapor ke si pekerja
keras dengan perintah adapter.notifyDataSetChanged() agar layarnya
di-refresh.
C. Simulator: Kasir (UI) vs Kurir Retrofit (Background)
Kasir (UI Thread)
Ngatur layar & tombol
Kurir Retrofit (Background)
Kerja jalur belakang
Jangan Panik Dulu! 😅
Kode di bawah ini cuma bayangan/ilustrasi aja biar kalian tahu gimana alur kerjanya nanti. Cara coding Retrofit dan narik data API secara utuh baru akan kita pelajari khusus di pertemuan-pertemuan nanti! Hari ini, kita fokus menguasai RecyclerView-nya dulu aja ya.
// Jadi Programmer Android nyewa "Jasa Kurir Ekspres" bernama RETROFIT!
public void tarikDataPakaiKurir() {
// Wajib minta Izin Internet di AndroidManifest.xml dlu ya!
// Kurir (Retrofit) otomatis lari ke Internet, Kasir (UI) tetep lancar!
KurirRetrofit.get("https://api.namaserver.com/kopi", new Callback() {
public void onPaketSampai(String jsonResponse) {
// 2. Urai teks JSON-nya (Looping 10.000x otomatis!)
JSONArray arr = new JSONArray(jsonResponse);
for (int i = 0; i < arr.length(); i++) {
JSONObject obj = arr.getJSONObject(i);
listData.add(new Kopi(
obj.getString("nama_kopi"),
obj.getString("harga"),
R.drawable.ic_default // Nanti kalian bakal belajar library GLIDE buat gambar!
));
}
// 3. WAJIB TERIAK: Hei Adapter, ada data baru masuk! Tolong refresh layarnya!
adapter.notifyDataSetChanged();
}
});
}
7. Tugas Implementasi (Challenge)
Pusing lihat kode Adapter di atas? Wajar! Semua developer Android juga merasakannya di awal. Cara mengalahkannya adalah dengan praktik langsung!
Misi Pahlawan Super:
- Buat project baru. Implementasikan RecyclerView untuk menampilkan "Daftar Pahlawan Nasional" atau "Daftar Tokoh Favoritmu" (Minimal 10 data).
- Kali ini, siapkan gambar (foto tokoh) minimal 3 yang berbeda dan masukkan ke folder
res/drawable. - Buat
item_row.xmlsecantik mungkin menggunakan CardView agar melengkung rapi. - Tantangan Tambahan: Coba ganti `LinearLayoutManager` menjadi `GridLayoutManager(this, 2)` di file Java-mu dan lihat perubahannya!
- Run aplikasinya di emulator (atau di HP Asli). Pastikan bisa di-scroll. Screenshot hasilnya! 📸
Cara memunculkan Toast saat item di-klik:
// Di dalam class Adapter, pada bagian onBindViewHolder:
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(
holder.itemView.getContext(),
"Kamu memilih: " + kopi.getNama(),
Toast.LENGTH_SHORT
).show();
}
});