Hiện danh sách đã phân trang

Hướng dẫn này dựa trên tổng quan về Thư viện phân trang, mô tả cách bạn có thể trình bày danh sách thông tin cho người dùng trong UI (giao diện người dùng) của ứng dụng, đặc biệt là khi thông tin này thay đổi.

Kết nối UI (giao diện người dùng) với mô hình chế độ xem

Bạn có thể kết nối một bản sao của LiveData<PagedList> với một PagedListAdapter, như minh hoạ trong đoạn mã sau:

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);
    }
}

Khi nguồn dữ liệu cung cấp các bản sao mới của PagedList, activity sẽ gửi các đối tượng này đến bộ chuyển đổi. Hoạt động triển khai PagedListAdapter xác định cách tính toán các bản cập nhật và tự động xử lý sự khác biệt giữa phân trang và danh sách. Do đó, ViewHolder chỉ cần ràng buộc với một mục cụ thể đã cung cấp:

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 sẽ xử lý các sự kiện tải trang bằng cách dùng đối tượng PagedList.Callback. Khi người dùng cuộn, PagedListAdapter sẽ gọi PagedList.loadAround() để cung cấp gợi ý cho PagedList cơ bản về những mục cần tìm nạp trong DataSource.

Triển khai lệnh gọi lại so sánh

Mẫu sau đây minh hoạ cách triển khai thủ công của areContentsTheSame(), trong đó so sánh các trường đối tượng có liên quan:

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);
    }
};

Vì bộ chuyển đổi của bạn bao gồm định nghĩa về việc so sánh các mục, nên bộ chuyển đổi sẽ tự động phát hiện các thay đổi đối với các mục này khi đối tượng PagedList mới được tải. Do đó, bộ chuyển đổi sẽ kích hoạt các hiệu ứng tải mục hiệu quả trong đối tượng RecyclerView.

So sánh bằng loại bộ chuyển đổi khác

Nếu bạn không kế thừa từ PagedListAdapter — chẳng hạn như bạn dùng thư viện cung cấp bộ chuyển đổi riêng — bạn vẫn có thể dùng chức năng khác biệt của bộ chuyển đổi thư viện Paging bằng cách trực tiếp xử lý đối tượng AsyncPagedListDiffer.

Cung cấp phần giữ chỗ trong UI (giao diện người dùng)

Trong trường hợp bạn muốn UI (giao diện người dùng) hiện một danh sách trước khi ứng dụng hoàn tất quá trình tìm nạp dữ liệu, bạn có thể hiện các mục danh sách trong phần giữ chỗ cho người dùng. PagedList xử lý trường hợp này bằng cách trình bày dữ liệu mục danh sách dưới dạng null cho đến khi dữ liệu được tải.

Phần giữ chỗ có những lợi ích sau:

  • Hỗ trợ thanh cuộn: PagedList cung cấp số lượng mục trong danh sách cho PagedListAdapter. Thông tin này cho phép bộ chuyển đổi vẽ một thanh cuộn để truyền tải kích thước đầy đủ của danh sách. Khi tải các trang mới, thanh cuộn sẽ không nhảy vì danh sách của bạn không thay đổi kích thước.
  • Không cần vòng quay đang tải: Vì kích thước danh sách đã được xác định, nên bạn không cần cảnh báo người dùng rằng nhiều mục khác đang tải. Phần giữ chỗ sẽ tự truyền tải thông tin đó.

Trước khi thêm khả năng hỗ trợ cho phần giữ chỗ, hãy lưu ý những điều kiện tiên quyết sau đây:

  • Yêu cầu tập dữ liệu có thể đếm được: Các bản sao của DataSource trong thư viện lưu trữ Room có thể đếm các mục một cách hiệu quả. Tuy nhiên, nếu bạn đang sử dụng giải pháp lưu trữ cục bộ tuỳ chỉnh hoặc cấu trúc dữ liệu chỉ dành cho mạng, thì bạn có thể tốn kém hoặc thậm chí không thể xác định có bao nhiêu mục bao gồm tập dữ liệu của bạn.
  • Yêu cầu bộ chuyển đổi tính đến các mục chưa tải: Bộ chuyển đổi hoặc cơ chế trình bày mà bạn dùng để chuẩn bị danh sách cho lạm phát cần phải xử lý các mục trong danh sách rỗng. Ví dụ: khi ràng buộc dữ liệu với ViewHolder, bạn cần cung cấp các giá trị mặc định để đại diện cho dữ liệu chưa tải.
  • Yêu cầu chế độ xem mục có cùng kích thước: Nếu kích thước mục trong danh sách có thể thay đổi theo nội dung của các mục đó, chẳng hạn như nội dung cập nhật trên mạng xã hội, thì việc phân chia giữa các mục sẽ không ổn. Chúng tôi thực sự khuyên bạn nên vô hiệu hoá phần giữ chỗ trong trường hợp này.

Gửi ý kiến phản hồi

Hãy chia sẻ phản hồi và ý kiến của bạn với chúng tôi thông qua các tài nguyên sau:

Công cụ theo dõi lỗi
Báo cáo sự cố để chúng tôi có thể sửa lỗi.

Tài nguyên khác

Để tìm hiểu thêm về Thư viện Paging, hãy tham khảo các tài nguyên sau.

Mẫu

Lớp học lập trình

Video