Menampilkan daftar yang dibagi-bagi

Panduan ini dibuat berdasarkan ringkasan Library Paging, yang menjelaskan cara menyajikan daftar informasi kepada pengguna di UI aplikasi Anda, terutama saat informasi ini berubah.

Menghubungkan UI ke model tampilan

Anda dapat menghubungkan instance LiveData<PagedList> ke PagedListAdapter, seperti yang ditunjukkan dalam cuplikan kode berikut:

Kotlin

class ConcertActivity : AppCompatActivity() {
    private val adapter = ConcertAdapter()

    // Use the 'by viewModels()' Kotlin property delegate
    // from the activity-ktx artifact
    private val viewModel: ConcertViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState);
        viewModel.concerts.observe(this, Observer { adapter.submitList(it) })
    }
}

Java

public class ConcertActivity extends AppCompatActivity {
    private ConcertAdapter adapter = new ConcertAdapter();
    private ConcertViewModel viewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = new ViewModelProvider(this).get(ConcertViewModel.class);
        viewModel.concertList.observe(this, adapter::submitList);
    }
}

Karena sumber data menyediakan instance PagedList baru, aktivitas akan mengirim objek ini ke adaptor. Implementasi PagedListAdapter menentukan cara update dikomputasi, serta otomatis menangani paging dan diffing daftar. Oleh karena itu, ViewHolder hanya perlu mengikat data ke item tertentu yang disediakan:

Kotlin

class ConcertAdapter() :
        PagedListAdapter<Concert, ConcertViewHolder>(DIFF_CALLBACK) {
    override fun onBindViewHolder(holder: ConcertViewHolder, position: Int) {
        val concert: Concert? = getItem(position)

        // Note that "concert" is a placeholder if it's null.
        holder.bindTo(concert)
    }

    companion object {
        private val DIFF_CALLBACK = ... // See Implement the diffing callback section.
    }
}

Java

public class ConcertAdapter
        extends PagedListAdapter<Concert, ConcertViewHolder> {
    protected ConcertAdapter() {
        super(DIFF_CALLBACK);
    }

    @Override
    public void onBindViewHolder(@NonNull ConcertViewHolder holder,
            int position) {
        Concert concert = getItem(position);

        // Note that "concert" can be null if it's a placeholder.
        holder.bindTo(concert);
    }

    private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK
            = ... // See Implement the diffing callback section.
}

PagedListAdapter menangani peristiwa pemuatan halaman menggunakan objek PagedList.Callback. Saat pengguna men-scroll, PagedListAdapter memanggil PagedList.loadAround() untuk memberikan petunjuk ke PagedList pokok terkait item yang harus diambil dari DataSource.

Menerapkan callback diffing

Contoh berikut menunjukkan implementasi manual areContentsTheSame(), yang membandingkan kolom-kolom objek yang relevan:

Kotlin

private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Concert>() {
    // The ID property identifies when items are the same.
    override fun areItemsTheSame(oldItem: Concert, newItem: Concert) =
            oldItem.id == newItem.id

    // If you use the "==" operator, make sure that the object implements
    // .equals(). Alternatively, write custom data comparison logic here.
    override fun areContentsTheSame(
            oldItem: Concert, newItem: Concert) = oldItem == newItem
}

Java

private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK =
        new DiffUtil.ItemCallback<Concert>() {

    @Override
    public boolean areItemsTheSame(Concert oldItem, Concert newItem) {
        // The ID property identifies when items are the same.
        return oldItem.getId() == newItem.getId();
    }

    @Override
    public boolean areContentsTheSame(Concert oldItem, Concert newItem) {
        // Don't use the "==" operator here. Either implement and use .equals(),
        // or write custom data comparison logic here.
        return oldItem.equals(newItem);
    }
};

Karena adaptor Anda menyertakan definisi untuk membandingkan item, adaptor akan otomatis mendeteksi perubahan pada item ini saat objek PagedList baru dimuat. Akibatnya, adaptor memicu animasi item yang efisien dalam objek RecyclerView Anda.

Menjalankan diffing menggunakan jenis adaptor berbeda

Jika memilih untuk tidak mewarisi dari PagedListAdapter—seperti saat Anda menggunakan library yang menyediakan adaptornya sendiri—Anda masih dapat menggunakan fungsi diffing adaptor Library Paging dengan menangani objek AsyncPagedListDiffer secara langsung.

Menyediakan placeholder di UI Anda

Jika ingin UI Anda menampilkan daftar sebelum aplikasi selesai mengambil data, Anda dapat menampilkan item daftar placeholder kepada pengguna. PagedList menangani kasus ini dengan menyajikan data item daftar sebagai null sampai data tersebut dimuat.

Placeholder memiliki manfaat sebagai berikut:

  • Dukungan untuk scroll bar: PagedList memberikan jumlah item daftar ke PagedListAdapter. Dengan informasi ini, adaptor dapat menggambar scroll bar yang menunjukkan ukuran penuh daftar. Saat halaman baru dimuat, scroll bar tidak akan melompat karena daftar tidak berubah ukuran.
  • Tidak perlu menampilkan indikator lingkaran berputar pemuatan: Karena ukuran daftar sudah diketahui, tidak perlu memberi tahu pengguna bahwa ada item lain yang dimuat. Placeholder itu sendiri sudah menyampaikan informasi tersebut.

Sebelum menambahkan dukungan untuk placeholder, perhatikan prasyarat berikut:

  • Diperlukan set data yang dapat dihitung: Instance DataSource dari library persistensi Room dapat menghitung itemnya sendiri secara efisien. Namun, jika Anda menggunakan solusi penyimpanan lokal kustom atau arsitektur data khusus jaringan, mungkin perlu banyak biaya atau bahkan tidak mungkin untuk menentukan jumlah item yang menyusun set data Anda.
  • Diperlukan adaptor untuk memperhitungkan item yang tidak dimuat: Adaptor atau mekanisme presentasi yang Anda gunakan untuk menyiapkan perluasan daftar harus dapat menangani item daftar null. Misalnya, saat mengikat data ke ViewHolder, Anda harus memberikan nilai default untuk mewakili data yang tidak dimuat.
  • Diperlukan tampilan item yang berukuran sama: Jika ukuran item daftar dapat berubah berdasarkan kontennya, misalnya seperti update jaringan sosial, crossfading antar-item bukanlah solusi yang tepat. Dalam hal ini, sebaiknya nonaktifkan placeholder.

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, pelajari referensi berikut.

Contoh

Codelab

Video