Paginasi — teknik pemuatan data halaman per halaman yang digunakan dalam aplikasi seluler dan layanan web untuk bekerja dengan kumpulan data besar. Menurut Android Developers Documentation (2025), implementasi paginasi yang benar mengurangi beban API, menghemat lalu lintas, dan meningkatkan pengalaman pengguna. Pemuatan halaman demi halaman memungkinkan aplikasi menampilkan konten secara bertahap, tanpa menunggu pemuatan semua data secara lengkap.
Poin Utama
Paginasi (dari Inggris pagination — pembagian halaman) — teknik membagi kumpulan data besar menjadi bagian-bagian berurutan (halaman). Dalam aplikasi seluler, paginasi digunakan saat memuat daftar pesan, umpan berita, katalog produk, riwayat pesanan, dan koleksi lain dengan jumlah catatan yang berpotensi tidak terbatas.
Tanpa paginasi, aplikasi harus memuat semua data sekaligus, yang menyebabkan waktu tunggu lama, konsumsi lalu lintas tinggi, dan kinerja tidak stabil pada perangkat lemah. Permintaan API dengan paginasi hanya mengembalikan satu porsi data dan meta-informasi untuk memuat berikutnya — dengan demikian aplikasi mengontrol volume informasi yang diterima.
Metrik utama paginasi: ukuran halaman (page size) — jumlah catatan dalam satu halaman (biasanya 10-50), dan nomor halaman atau kursor — penunjuk posisi saat ini dalam kumpulan data. Pemilihan ukuran halaman tergantung pada jenis data: untuk elemen kompak (nama) cukup 20-30, untuk kartu dengan gambar — 10-15.
Perangkat seluler memiliki sumber daya terbatas: volume RAM, kecepatan prosesor, dan batas lalu lintas. Paginasi menyelesaikan tiga tugas utama: pengurangan konsumsi memori (hanya elemen yang terlihat disimpan di memori), percepatan tampilan pertama (porsi pertama dimuat lebih cepat dari seluruh kumpulan) dan penghematan lalu lintas (data dimuat hanya saat pengguna menggulir daftar).
Ada empat jenis utama paginasi, masing-masing menyelesaikan tugas spesifik. Pemilihan metode tergantung pada persyaratan konsistensi data, arsitektur API, jenis penyimpanan, dan kompleksitas implementasi yang diizinkan di sisi klien dan server.
| Jenis | Prinsip Kerja | Stabilitas | Kecepatan pada volume besar |
|---|---|---|---|
| Offset | LIMIT + OFFSET di SQL | rendah | menurun dengan bertambahnya OFFSET |
| Cursor | WHERE id > last_id | tinggi | stabil (O(log n)) |
| Keyset | WHERE key > last_key | tinggi | stabil (O(log n)) |
| Time-based | WHERE created_at < last_time | sedang | stabil dengan indeks |
Paginasi Offset cocok untuk kumpulan data statis atau jarang diperbarui, ketika implementasi sederhana penting. Cursor dan Keyset — untuk data dinamis dengan penyisipan sering. Time-based — untuk umpan kronologis, di mana catatan diurutkan berdasarkan waktu pembuatan. Standar GraphQL Relay menggunakan paginasi cursor sebagai satu-satunya metode yang direkomendasikan.
Paginasi Offset — jenis pemuatan halaman per halaman yang paling sederhana. Klien mengirimkan parameter page dan limit (atau offset dan limit), server menerapkan SQL OFFSET dan LIMIT. Misalnya, page=2, limit=20 akan mengembalikan catatan 21 hingga 40. Metode ini intuitif dan mudah diimplementasikan pada tumpukan teknologi apa pun.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items")
async def get_items(
page: int = Query(default=1, ge=1),
limit: int = Query(default=20, le=100)
):
offset = (page - 1) * limit
items = await fetch_items(offset, limit)
total = await count_items()
return {
"items": items,
"total": total,
"page": page,
"pages": (total + limit - 1) // limit
}
Kekurangan utama paginasi Offset — masalah catatan yang terlewat dan duplikat. Jika di antara dua permintaan ditambahkan catatan baru ke tabel, OFFSET bergeser: pengguna dapat melihat catatan yang sama dua kali atau melewatkan catatan baru. Ini kritis untuk umpan berita dan obrolan di mana konsistensi penting.
Masalah lain — penurunan kinerja pada OFFSET besar. Basis data harus memindai dan melewatkan catatan offset pertama sebelum mengembalikan hasil. Pada offset=100000 bahkan dengan LIMIT 20, server akan menghabiskan waktu yang signifikan untuk memindai. PostgreSQL dan MySQL menunjukkan penurunan kecepatan linier seiring bertambahnya OFFSET.
Paginasi Offset tetap menjadi pilihan terbaik untuk: panel administrasi (data jarang berubah, navigasi antar halaman diperlukan), laporan dan log historis (potongan data tetap), katalog dengan pemfilteran (dapat menavigasi ke halaman mana pun). Offset juga paling mudah diimplementasikan di sisi klien — RecyclerView dengan Paging 3 mendukungnya langsung.
Paginasi Keyset menggunakan kunci unik (biasanya kunci utama) untuk memfilter catatan. Alih-alih OFFSET, permintaan menggunakan WHERE id > last_seen_id. Ini memastikan kinerja stabil terlepas dari jumlah catatan dan tidak adanya duplikat saat penyisipan, karena catatan baru selalu memiliki id yang lebih besar.
-- Paginasi Offset (bermasalah)
SELECT * FROM posts
ORDER BY id
LIMIT 20 OFFSET 100;
-- Paginasi Keyset (stabil)
SELECT * FROM posts
WHERE id > 100
ORDER BY id
LIMIT 20;
Paginasi Time-based (atau kursor waktu) menggunakan stempel waktu created_at untuk navigasi. Klien mengirimkan timestamp catatan terakhir yang dimuat, server mengembalikan catatan yang dibuat sebelum atau setelah stempel waktu ini. Metode ini populer di jaringan sosial dan umpan berita, di mana urutan catatan ditentukan oleh waktu publikasi.
Keistimewaan paginasi Time-based — kemungkinan duplikat jika dua catatan dibuat dalam milidetik yang sama. Untuk mengatasi masalah ini, kunci time-based digabungkan dengan id unik: WHERE (created_at, id) < (last_time, last_id). Kursor gabungan semacam itu menjamin keunikan setiap catatan dan urutan yang tepat.
Paginasi Keyset memerlukan kolom dengan nilai unik dan meningkat secara monoton (id auto-increment, UUID v7). Time-based cocok untuk tabel apa pun dengan created_at, tetapi memerlukan pemrosesan duplikat tambahan. Perbedaan utama: Keyset bekerja stabil pada operasi penyisipan apa pun, sementara Time-based sensitif terhadap stempel waktu yang identik.
Pemilihan jenis paginasi tergantung pada sifat data dan persyaratan pengalaman pengguna. Di bawah ini adalah rekomendasi untuk skenario umum dalam pengembangan seluler. Tidak ada solusi universal — setiap metode memiliki area penerapan di mana ia optimal.
Pustaka Android Paging 3 mendukung semua jenis paginasi melalui PagingSource. Untuk Offset — PagingSource dengan kunci Int (page), untuk Cursor — dengan kunci String atau Long (cursor). PagingSource secara otomatis mengelola pemuatan, caching, dan percobaan ulang saat terjadi kesalahan.
class PostPagingSource(
private val api: PostApi
) : PagingSource<Long, Post>() {
override suspend fun load(
params: LoadParams<Long>
): LoadResult<Long, Post> {
val cursor = params.key ?: Long.MAX_VALUE
return try {
val response = api.getPosts(cursor, params.loadSize)
LoadResult.Page(
data = response.items,
prevKey = null,
nextKey = response.items.lastOrNull()?.id
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override fun getRefreshKey(state: PagingState<Long, Post>): Long? {
return state.anchorPosition?.let {
state.closestItemToPosition(it)?.id
}
}
}
Ukuran halaman mempengaruhi kecepatan pemuatan dan persepsi kinerja. Untuk aplikasi seluler, rentang optimal adalah 10-25 elemen per halaman. Kurang dari 10 — terlalu sering permintaan ke API dan gulir yang tersendat. Lebih dari 25 — pemuatan lambat porsi pertama di jaringan lambat.
Untuk gambar dan video, ukuran halaman dikurangi menjadi 5-10, karena setiap elemen memerlukan waktu tambahan untuk memuat media. Untuk daftar dengan elemen teks (komentar, log), ukuran dapat ditingkatkan menjadi 30-50 catatan. Disarankan agar ukuran halaman dapat dikonfigurasi melalui API, sehingga klien dapat beradaptasi dengan kondisi jaringan yang berbeda.
Pertanyaan yang Sering Diajukan
Paginasi — memuat data dalam porsi, tidak semuanya sekaligus. Seperti dalam buku: Anda membaca satu halaman, lalu beralih ke halaman berikutnya. Dalam aplikasi, ini berarti saat menggulir daftar, porsi data berikutnya dimuat, bukan seluruh daftar sekaligus, yang menghemat lalu lintas dan memori.
Offset menghitung catatan: “lewati 20, kembalikan 10 berikutnya”. Jika di antara pemuatan ditambahkan catatan baru — penomoran bergeser. Cursor menggunakan pengidentifikasi unik catatan terakhir: “kembalikan 10 catatan setelah ID = 100”. Catatan baru tidak mempengaruhi posisi.
Untuk aplikasi seluler optimal 10-25 elemen. Untuk daftar dengan gambar — 5-10, untuk umpan teks — 20-30. Ukuran tergantung pada ukuran rata-rata satu elemen: semakin berat elemen, semakin kecil halaman untuk tampilan cepat.
Gunakan pustaka Paging 3 dari Android Jetpack. Ini menyediakan PagingSource untuk pemuatan, PagingData untuk aliran reaktif, dan PagingDataAdapter untuk pemuatan otomatis saat menggulir. Pustaka mendukung paginasi Offset, Cursor, dan Keyset melalui PagingSource kustom.
Gulir tak terbatas — pola UI di mana porsi data baru dimuat secara otomatis saat mendekati akhir daftar. Paginasi — mekanisme memuat data dalam porsi, dan gulir tak terbatas adalah salah satu cara menampilkannya. Alternatifnya adalah tombol “Muat lebih banyak”.
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