Dokumen ini dibuat berdasarkan ringkasan Library Paging, yang membahas cara menyesuaikan solusi pemuatan data aplikasi untuk memenuhi kebutuhan arsitektur aplikasi Anda.
Membuat daftar yang dapat diamati
Biasanya, kode UI Anda mengamati objek LiveData<PagedList> (atau, jika
Anda menggunakan RxJava2, objek Flowable<PagedList> atau
Observable<PagedList>), yang berada di ViewModel aplikasi Anda.
Objek yang dapat diamati ini membentuk koneksi antara presentasi dan konten
data daftar aplikasi Anda.
Untuk membuat salah satu objek PagedList yang dapat diamati ini, teruskan instance DataSource.Factory ke objek LivePagedListBuilder atau RxPagedListBuilder. Objek DataSource memuat halaman untuk satu PagedList. Class factory membuat instance baru PagedList sebagai respons terhadap update konten, seperti pembatalan tabel database dan pemuatan ulang jaringan. Library persistensi Room dapat menyediakan objek DataSource.Factory
untuk Anda, atau Anda dapat membuatnya sendiri.
Cuplikan kode berikut menunjukkan cara membuat instance baru
LiveData<PagedList> di class ViewModel aplikasi Anda menggunakan kemampuan
membangun DataSource.Factory Room:
ConcertDao
Kotlin
@Dao
interface ConcertDao {
// The Int type parameter tells Room to use a PositionalDataSource
// object, with position-based loading under the hood.
@Query("SELECT * FROM concerts ORDER BY date DESC")
fun concertsByDate(): DataSource.Factory<Int, Concert>
}
Java
@Dao
public interface ConcertDao {
// The Integer type parameter tells Room to use a PositionalDataSource
// object, with position-based loading under the hood.
@Query("SELECT * FROM concerts ORDER BY date DESC")
DataSource.Factory<Integer, Concert> concertsByDate();
}
ConcertViewModel
Kotlin
// The Int type argument corresponds to a PositionalDataSource object.
val myConcertDataSource : DataSource.Factory<Int, Concert> =
concertDao.concertsByDate()
val concertList = myConcertDataSource.toLiveData(pageSize = 50)
Java
// The Integer type argument corresponds to a PositionalDataSource object.
DataSource.Factory<Integer, Concert> myConcertDataSource =
concertDao.concertsByDate();
LiveData<PagedList<Concert>> concertList =
LivePagedListBuilder(myConcertDataSource, /* page size */ 50).build();
Menentukan konfigurasi paging Anda sendiri
Untuk mengonfigurasi LiveData<PagedList> lebih lanjut untuk kasus lanjutan, Anda juga dapat menentukan konfigurasi paging Anda sendiri. Secara khusus, Anda dapat menentukan
atribut berikut:
- Ukuran halaman: Jumlah item di setiap halaman.
- Jarak prefetch: Dengan item terakhir yang terlihat di UI aplikasi, jumlah item di luar item terakhir ini yang harus dicoba diambil oleh Library Paging terlebih dahulu. Nilai ini harus beberapa kali lebih besar dari ukuran halaman.
- Keberadaan placeholder: Menentukan apakah UI menampilkan placeholder untuk item daftar yang belum selesai dimuat. Untuk pembahasan tentang manfaat dan kelemahan penggunaan placeholder, pelajari cara Menyediakan placeholder di UI Anda.
Jika Anda ingin lebih mengontrol kapan Library Paging memuat daftar dari
database aplikasi, teruskan objek Executor kustom ke
LivePagedListBuilder, seperti yang ditunjukkan dalam cuplikan kode berikut:
ConcertViewModel
Kotlin
val myPagingConfig = Config(
pageSize = 50,
prefetchDistance = 150,
enablePlaceholders = true
)
// The Int type argument corresponds to a PositionalDataSource object.
val myConcertDataSource : DataSource.Factory<Int, Concert> =
concertDao.concertsByDate()
val concertList = myConcertDataSource.toLiveData(
pagingConfig = myPagingConfig,
fetchExecutor = myExecutor
)
Java
PagedList.Config myPagingConfig = new PagedList.Config.Builder()
.setPageSize(50)
.setPrefetchDistance(150)
.setEnablePlaceholders(true)
.build();
// The Integer type argument corresponds to a PositionalDataSource object.
DataSource.Factory<Integer, Concert> myConcertDataSource =
concertDao.concertsByDate();
LiveData<PagedList<Concert>> concertList =
new LivePagedListBuilder<>(myConcertDataSource, myPagingConfig)
.setFetchExecutor(myExecutor)
.build();
Memilih jenis sumber data yang benar
Penting untuk terhubung ke sumber data yang menangani struktur data sumber Anda paling baik:
- Gunakan
PageKeyedDataSourcejika halaman yang Anda muat menyematkan kunci berikutnya atau sebelumnya. Misalnya, jika Anda mengambil postingan media sosial dari jaringan, Anda mungkin perlu meneruskan tokennextPagedari satu pemuatan ke pemuatan berikutnya. - Gunakan
ItemKeyedDataSourcejika Anda perlu menggunakan data dari item N untuk mengambil item N+1. Misalnya, jika Anda mengambil komentar berangkai untuk aplikasi diskusi, Anda mungkin perlu meneruskan ID komentar terakhir untuk mendapatkan konten komentar berikutnya. - Gunakan
PositionalDataSourcejika Anda perlu mengambil halaman data dari lokasi mana pun yang Anda pilih di datastore. Class ini mendukung permintaan kumpulan item data yang dimulai dari lokasi mana pun yang Anda pilih. Misalnya, permintaan mungkin menampilkan 50 item data yang dimulai dengan lokasi 1500.
Memberi tahu jika data tidak valid
Saat menggunakan Library Paging, lapisan data bertanggung jawab memberi tahu
lapisan lain di aplikasi Anda saat tabel atau baris menjadi usang. Untuk melakukannya, panggil
invalidate() dari class DataSource yang telah Anda pilih untuk
aplikasi Anda.
Membuat sumber data Anda sendiri
Jika menggunakan solusi data lokal kustom, atau jika Anda memuat data langsung dari
jaringan, Anda dapat mengimplementasikan salah satu subclass DataSource. Cuplikan
kode berikut menunjukkan sumber data yang dihitung dari waktu mulai
konser tertentu:
Kotlin
class ConcertTimeDataSource() :
ItemKeyedDataSource<Date, Concert>() {
override fun getKey(item: Concert) = item.startTime
override fun loadInitial(
params: LoadInitialParams<Date>,
callback: LoadInitialCallback<Concert>) {
val items = fetchItems(params.requestedInitialKey,
params.requestedLoadSize)
callback.onResult(items)
}
override fun loadAfter(
params: LoadParams<Date>,
callback: LoadCallback<Concert>) {
val items = fetchItemsAfter(
date = params.key,
limit = params.requestedLoadSize)
callback.onResult(items)
}
}
Java
public class ConcertTimeDataSource
extends ItemKeyedDataSource<Date, Concert> {
@NonNull
@Override
public Date getKey(@NonNull Concert item) {
return item.getStartTime();
}
@Override
public void loadInitial(@NonNull LoadInitialParams<Date> params,
@NonNull LoadInitialCallback<Concert> callback) {
List<Concert> items =
fetchItems(params.key, params.requestedLoadSize);
callback.onResult(items);
}
@Override
public void loadAfter(@NonNull LoadParams<Date> params,
@NonNull LoadCallback<Concert> callback) {
List<Concert> items =
fetchItemsAfter(params.key, params.requestedLoadSize);
callback.onResult(items);
}
}
Kemudian, Anda dapat memuat data yang disesuaikan ini ke dalam objek PagedList dengan membuat subclass konkret dari DataSource.Factory. Cuplikan kode berikut menunjukkan
cara membuat instance baru sumber data kustom yang ditentukan dalam cuplikan kode
sebelumnya:
Kotlin
class ConcertTimeDataSourceFactory :
DataSource.Factory<Date, Concert>() {
val sourceLiveData = MutableLiveData<ConcertTimeDataSource>()
var latestSource: ConcertDataSource?
override fun create(): DataSource<Date, Concert> {
latestSource = ConcertTimeDataSource()
sourceLiveData.postValue(latestSource)
return latestSource
}
}
Java
public class ConcertTimeDataSourceFactory
extends DataSource.Factory<Date, Concert> {
private MutableLiveData<ConcertTimeDataSource> sourceLiveData =
new MutableLiveData<>();
private ConcertDataSource latestSource;
@Override
public DataSource<Date, Concert> create() {
latestSource = new ConcertTimeDataSource();
sourceLiveData.postValue(latestSource);
return latestSource;
}
}
Mempertimbangkan cara kerja pembaruan konten
Saat Anda membuat objek PagedList yang dapat diamati, pertimbangkan cara kerja pembaruan konten. Jika Anda memuat data langsung dari database Room,
update akan otomatis dikirim ke UI aplikasi Anda.
Saat menggunakan API jaringan halaman, Anda biasanya memiliki interaksi pengguna, seperti
"geser untuk memuat ulang", yang berfungsi sebagai sinyal untuk membatalkan validasi DataSource
yang terakhir Anda gunakan. Kemudian, Anda meminta instance baru dari sumber data tersebut. Cuplikan kode berikut menunjukkan perilaku ini:
Kotlin
class ConcertActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// ...
concertTimeViewModel.refreshState.observe(this, Observer {
// Shows one possible way of triggering a refresh operation.
swipeRefreshLayout.isRefreshing =
it == MyNetworkState.LOADING
})
swipeRefreshLayout.setOnRefreshListener {
concertTimeViewModel.invalidateDataSource()
}
}
}
class ConcertTimeViewModel(firstConcertStartTime: Date) : ViewModel() {
val dataSourceFactory = ConcertTimeDataSourceFactory(firstConcertStartTime)
val concertList: LiveData<PagedList<Concert>> =
dataSourceFactory.toLiveData(
pageSize = 50,
fetchExecutor = myExecutor
)
fun invalidateDataSource() =
dataSourceFactory.sourceLiveData.value?.invalidate()
}
Java
public class ConcertActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
// ...
viewModel.getRefreshState()
.observe(this, new Observer<NetworkState>() {
// Shows one possible way of triggering a refresh operation.
@Override
public void onChanged(@Nullable MyNetworkState networkState) {
swipeRefreshLayout.isRefreshing =
networkState == MyNetworkState.LOADING;
}
};
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshListener() {
@Override
public void onRefresh() {
viewModel.invalidateDataSource();
}
});
}
}
public class ConcertTimeViewModel extends ViewModel {
private LiveData<PagedList<Concert>> concertList;
private DataSource<Date, Concert> mostRecentDataSource;
public ConcertTimeViewModel(Date firstConcertStartTime) {
ConcertTimeDataSourceFactory dataSourceFactory =
new ConcertTimeDataSourceFactory(firstConcertStartTime);
mostRecentDataSource = dataSourceFactory.create();
concertList = new LivePagedListBuilder<>(dataSourceFactory, 50)
.setFetchExecutor(myExecutor)
.build();
}
public void invalidateDataSource() {
mostRecentDataSource.invalidate();
}
}
Menyediakan pemetaan data
Library Paging mendukung transformasi berbasis item dan berbasis halaman untuk item
yang dimuat oleh DataSource.
Dalam cuplikan kode berikut, gabungan antara nama konser dan tanggal konser dipetakan ke satu string yang berisi nama dan tanggal:
Kotlin
class ConcertViewModel : ViewModel() {
val concertDescriptions : LiveData<PagedList<String>>
init {
val concerts = database.allConcertsFactory()
.map { "${it.name} - ${it.date}" }
.toLiveData(pageSize = 50)
}
}
Java
public class ConcertViewModel extends ViewModel {
private LiveData<PagedList<String>> concertDescriptions;
public ConcertViewModel(MyDatabase database) {
DataSource.Factory<Integer, Concert> factory =
database.allConcertsFactory().map(concert ->
concert.getName() + "-" + concert.getDate());
concertDescriptions = new LivePagedListBuilder<>(
factory, /* page size */ 50).build();
}
}
Cara ini dapat berguna jika Anda ingin menggabung, mengonversi, atau menyiapkan item setelah dimuat. Karena pekerjaan ini dilakukan di eksekutor pengambilan, Anda dapat melakukan pekerjaan yang berpotensi mahal, seperti membaca dari disk atau membuat kueri database terpisah.
Berikan masukan
Sampaikan masukan dan ide Anda kepada kami melalui resource berikut:
- Issue tracker

- Laporkan masalah agar kami dapat memperbaiki bug.
Referensi lainnya
Untuk mempelajari Library Paging lebih lanjut, lihat referensi berikut.
Contoh
Codelab
Video
- Android Jetpack: mengelola daftar tak terbatas dengan RecyclerView dan Paging (Google I/O '18)
- Android Jetpack: Paging
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Bermigrasi ke Paging 3
- Ringkasan library Paging 2
- Menampilkan daftar yang di-page