Lazy Loading — strategi pemuatan data, gambar, dan komponen yang ditunda, di mana sumber daya diminta bukan saat aplikasi dimulai, melainkan saat benar-benar dibutuhkan oleh pengguna. Menurut Android Paging 3 Guide, pemuatan lambat daftar mengurangi konsumsi memori sebesar 60–80% saat bekerja dengan kumpulan data besar. Inisialisasi yang ditunda — prinsip kunci yang mendasari semua implementasi Lazy Loading.
Poin utama
Lazy Loading (pemuatan lambat, pemuatan ditunda) — pola desain dan optimasi di mana sumber daya aplikasi dimuat bukan saat startup, melainkan langsung sebelum digunakan. Dalam pengembangan mobile, Lazy Loading diterapkan pada tiga kategori utama: data (paginasi daftar), gambar (pemuatan saat scroll) dan komponen (stack dan view lambat).
Kebalikan dari Lazy Loading adalah Eager Loading (pemuatan rakus), ketika semua sumber daya dimuat saat startup layar. Eager Loading lebih sederhana dalam implementasi, tetapi mengonsumsi lebih banyak memori dan memperlama waktu tampilan pertama. Untuk daftar dengan ribuan elemen, Eager Loading menyebabkan OOM (Out of Memory) pada perangkat dengan memori terbatas. Lazy Loading memecahkan masalah ini dengan hanya memuat apa yang terlihat di layar dan menambahkan sisanya saat scroll.
Dalam konteks iOS dan Android, Lazy Loading diimplementasikan di berbagai level. SwiftUI menyediakan LazyVStack dan LazyHStack untuk rendering lambat. UIKit menggunakan UITableView dengan dequeueReusableCell. Android — RecyclerView dengan pool ViewHolder. Di level data — Room dengan Paging 3 dan Core Data dengan NSFetchedResultsController. Pemilihan teknologi spesifik tergantung pada stack dan kebutuhan performa.
Prinsip sentral Lazy Loading — memuat jumlah data yang tepat yang diperlukan untuk keadaan layar saat ini, ditambah buffer awal untuk scroll yang mulus. Pendekatan ini didasarkan pada dua mekanisme: pelacakan visibilitas dan virtualisasi elemen.
Mekanisme pelacakan menentukan elemen mana yang berada di area layar yang terlihat (viewport). Di Android, ini dilakukan oleh LinearLayoutManager atau GridLayoutManager melalui metode findFirstVisibleItemPosition dan findLastVisibleItemPosition. Di iOS, UIScrollView menyediakan bounds.origin.y dan contentOffset.height untuk menghitung area yang terlihat. Ketika elemen memasuki viewport (atau buffer prefetch), pemuatannya dimulai. Ketika elemen meninggalkan layar, sumber dayanya dapat dibebaskan atau dipindahkan ke cache.
// Android — pelacakan visibilitas di RecyclerView
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
val lastVisible = layoutManager.findLastVisibleItemPosition()
val totalCount = layoutManager.itemCount
// Kami memuat halaman berikutnya jika tersisa kurang dari 5 elemen < 5 elemen
if (lastVisible >= totalCount - 5) {
loadMoreItems()
}
}
})
Buffer Prefetch — pemuatan awal elemen yang akan segera muncul di layar. RecyclerView mendukung GapWorker.Prefetch melalui layoutManager.setItemPrefetchEnabled(true). iOS UITableView mendukung prefetching melalui UITableViewDataSourcePrefetching. Ukuran buffer prefetch biasanya 1–2 layar ke depan, memberikan kompromi antara kelancaran scroll dan konsumsi memori. Terlalu besar buffer prefetch meniadakan keunggulan Lazy Loading, terlalu kecil — menciptakan tempat kosong saat scroll cepat.
Gambar — jenis sumber daya terberat di aplikasi mobile. Satu foto 12 MP dapat memakan 3–5 MB dalam bentuk tidak terkompresi. Lazy Loading gambar mencegah pemuatan ratusan gambar tak terlihat ke memori, yang akan fatal untuk daftar komentar pengguna atau katalog produk.
Glide — pustaka pemuatan gambar paling populer untuk Android dengan dukungan caching, transformasi, dan animasi. Coil — alternatif lebih ringan yang ditulis dalam Kotlin menggunakan coroutine. Kedua pustaka secara otomatis menghentikan pemuatan saat ImageView meninggalkan layar dan membatalkan permintaan saat ViewHolder digunakan kembali. Coil menggunakan coroutine dan berukuran ~1.5 MB dibandingkan ~4 MB Glide, menjadikannya pilihan utama untuk proyek yang fokus pada ukuran APK.
// Coil — pemuatan lambat gambar
imageView.load("https://example.com/image.jpg") {
crossfade(true)
placeholder(R.drawable.placeholder)
size(512, 512)
memoryCachePolicy(CachePolicy.ENABLED)
}
Kingfisher — pustaka iOS dengan dukungan Swift Concurrency, caching ke disk dan memori, serta prefetching untuk UICollectionView. SDWebImage — pustaka yang lebih tua dengan akar Objective-C tetapi dengan dukungan Swift. Kedua pustaka terintegrasi dengan UIImageView dan secara otomatis mengelola siklus hidup pemuatan: membatalkan permintaan saat sel digunakan kembali, memuat gambar hanya saat sel terlihat dan membebaskan memori saat notifikasi kekurangan memori.
Daftar besar data — area penerapan utama Lazy Loading di aplikasi mobile. Feed berita, katalog produk, chat, riwayat transaksi — setiap layar dengan daftar yang berpotensi tak terbatas memerlukan paginasi dan pemuatan yang ditunda.
Paging 3 — pustaka dari Android Jetpack yang mengimplementasikan siklus lengkap pemuatan lambat: permintaan data dari RemoteMediator (API + database), caching di Room, pengiriman secara halaman melalui PagingData dan tampilan melalui AsyncPagingDataAdapter. Paging 3 mendukung tiga jenis paginasi: Page-based (halaman), Item-based (offset/limit) dan Key-based (kunci paginasi dari API). Separator — dukungan bawaan untuk pemisah antar halaman untuk indikator pemuatan.
// Paging 3 — pemuatan lambat dari API
class ArticlePagingSource(
private val api: ArticleApi
) : PagingSource<Int, Article>() {
override suspend fun load(
params: LoadParams<Int>
): LoadResult<Int, Article> {
return try {
val page = params.key ?: 1
val response = api.getArticles(page)
LoadResult.Page(
data = response.items,
prevKey = page.takeIf { it > 1 }?.dec(),
nextKey = page + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
}
LazyVStack — kontainer bawaan SwiftUI yang membuat dan merender elemen hanya saat muncul di layar. Tidak seperti VStack yang segera menghitung layout semua elemen anak, LazyVStack menunda pembuatan view hingga elemen menjadi terlihat atau memasuki rentang prefetch. LazyHStack — padanan horizontal untuk carousel. Untuk daftar volume besar, Apple merekomendasikan penggunaan List yang secara internal bekerja seperti LazyVStack dengan daur ulang bawaan tambahan.
// SwiftUI — LazyVStack dengan pemuatan lambat
ScrollView {
LazyVStack(spacing: 8) {
ForEach(articles) { article in
ArticleRow(article: article)
.onAppear {
if article == articles.last {
viewModel.loadMore()
}
}
}
}
}
Pemuatan lambat komponen UI — teknik di mana bagian antarmuka (header, footer, bagian pengaturan, tab) dibuat bukan saat startup layar, tetapi saat pertama kali diakses. Ini mempercepat render awal dan mengurangi beban pada main thread.
ViewStub — placeholder View ringan di Android yang tidak memakan tempat di layout dan tidak membuat View anak hingga pemanggilan inflate(). Ideal untuk bagian yang jarang digunakan: panel pencarian, pengaturan lanjutan, blok iklan. Pemuatan lambat Fragment — teknik di mana Fragment.onCreateView ditunda hingga pengguna beralih ke tab tersebut. Diimplementasikan melalui isVisible atau UserVisibleHint di ViewPager.
AndroidX menyediakan SplitInstallManager untuk pemuatan lambat modul sesuai permintaan. Modul pengaturan, diagnostik, atau fungsi tambahan dimuat sebagai modul Dynamic Feature hanya saat permintaan pertama pengguna. Ini mengurangi ukuran dasar aplikasi sebesar 30–50% dan sekaligus mengimplementasikan prinsip Lazy Loading tidak hanya di level data, tetapi juga kode.
TabView di SwiftUI memuat konten setiap tab secara lambat — hanya saat tab diaktifkan. UIKit UITabBarController secara default membuat semua kontroler anak saat startup, tetapi perilaku ini dapat diubah dengan tidak menambahkannya ke tabBarController.viewControllers segera, melainkan menambahkannya saat perpindahan. UIStackView dengan arrangedSubviews yang ditambahkan secara dinamis juga mengikuti prinsip Lazy Loading — tambahkan Subview hanya saat pengguna melakukan tindakan yang memerlukan bagian antarmuka tersebut.
Untuk optimasi pemuatan layar secara keseluruhan, gabungkan Lazy Loading di semua level: ViewStub untuk bagian yang jarang digunakan, Paging 3 untuk data, Glide/Coil untuk gambar dan inisialisasi lambat ViewModel melalui Hilt/Dagger Scopes atau Swinject. Pendekatan seperti ini memberikan layar yang dimuat dalam 200–400 ms bahkan pada perangkat murah dengan RAM 3 GB.
Pertanyaan yang sering diajukan
Jika layar dijamin menampilkan sedikit elemen (hingga 20) dan semuanya diperlukan segera — Lazy Loading berlebihan. Untuk daftar yang jarang di-scroll, Eager Loading bisa lebih sederhana dan lebih cepat diimplementasikan tanpa kehilangan performa yang signifikan.
Mengurangi konsumsi memori puncak 3–10 kali untuk daftar besar, karena hanya elemen yang terlihat dan buffer prefetch yang disimpan di memori. Namun, penambahan prefetch dan caching gambar menciptakan konsumsi memori sedang yang perlu dikelola.
List lebih disukai untuk data homogen dengan kemampuan swipe, drag, dan seleksi bawaan. LazyVStack — untuk layout kustom dengan tipe sel yang berbeda, bagian, dan jarak non-standar. List secara internal bekerja seperti LazyVStack dengan fungsionalitas tambahan.
Di Android gunakan Layout Inspector untuk melihat hierarki View: pada Lazy Loading sebagian besar elemen harus tidak ada di pohon. Di iOS — Xcode Debug View Hierarchy. Jika saat scroll semua elemen ada — Lazy Loading tidak berfungsi.
Kedua parameter penting, tetapi prioritas tergantung pada platform. Di iOS dengan ARC dan manajemen memori yang efisien, prioritas adalah kecepatan muat. Di Android dengan JVM dan GC, prioritas adalah penghematan memori, karena setiap alokasi di main thread dapat menyebabkan GC-freeze.
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