Display paged lists

This guide builds upon the Paging Library overview, describing how you can present lists of information to users in your app's UI, particularly when this information changes.

Connect your UI to your view model

You can connect an instance of LiveData<PagedList> to a PagedListAdapter, as shown in the following code snippet:

Kotlin

classConcertActivity:AppCompatActivity(){
privatevaladapter=ConcertAdapter()
// Use the 'by viewModels()' Kotlin property delegate
// from the activity-ktx artifact
privatevalviewModel:ConcertViewModelbyviewModels()
overridefunonCreate(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState);
viewModel.concerts.observe(this,Observer{adapter.submitList(it)})
}
}

Java

publicclass ConcertActivityextendsAppCompatActivity{
privateConcertAdapteradapter=newConcertAdapter();
privateConcertViewModelviewModel;
@Override
publicvoidonCreate(@NullableBundlesavedInstanceState){
super.onCreate(savedInstanceState);
viewModel=newViewModelProvider(this).get(ConcertViewModel.class);
viewModel.concertList.observe(this,adapter::submitList);
}
}

As data sources provide new instances of PagedList, the activity sends these objects to the adapter. The PagedListAdapter implementation defines how updates are computed, and it automatically handles paging and list diffing. Therefore, your ViewHolder only needs to bind to a particular provided item:

Kotlin

classConcertAdapter():
PagedListAdapter<Concert,ConcertViewHolder>(DIFF_CALLBACK){
overridefunonBindViewHolder(holder:ConcertViewHolder,position:Int){
valconcert:Concert? =getItem(position)
// Note that "concert" is a placeholder if it's null.
holder.bindTo(concert)
}
companionobject{
privatevalDIFF_CALLBACK=...// See Implement the diffing callback section.
}
}

Java

publicclass ConcertAdapter
extendsPagedListAdapter<Concert,ConcertViewHolder>{
protectedConcertAdapter(){
super(DIFF_CALLBACK);
}
@Override
publicvoidonBindViewHolder(@NonNullConcertViewHolderholder,
intposition){
Concertconcert=getItem(position);
// Note that "concert" can be null if it's a placeholder.
holder.bindTo(concert);
}
privatestaticDiffUtil.ItemCallback<Concert>DIFF_CALLBACK
=...// See Implement the diffing callback section.
}

The PagedListAdapter handles page load events using a PagedList.Callback object. As the user scrolls, the PagedListAdapter calls PagedList.loadAround() to provide hints to the underlying PagedList as to which items it should fetch from the DataSource.

Implement the diffing callback

The following sample shows a manual implementation of areContentsTheSame(), which compares relevant object fields:

Kotlin

privatevalDIFF_CALLBACK=object:DiffUtil.ItemCallback<Concert>(){
// The ID property identifies when items are the same.
overridefunareItemsTheSame(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.
overridefunareContentsTheSame(
oldItem:Concert,newItem:Concert)=oldItem==newItem
}

Java

privatestaticDiffUtil.ItemCallback<Concert>DIFF_CALLBACK=
newDiffUtil.ItemCallback<Concert>(){
@Override
publicbooleanareItemsTheSame(ConcertoldItem,ConcertnewItem){
// The ID property identifies when items are the same.
returnoldItem.getId()==newItem.getId();
}
@Override
publicbooleanareContentsTheSame(ConcertoldItem,ConcertnewItem){
// Don't use the "==" operator here. Either implement and use .equals(),
// or write custom data comparison logic here.
returnoldItem.equals(newItem);
}
};

Because your adapter includes your definition of comparing items, the adapter automatically detects changes to these items when a new PagedList object is loaded. As a result, the adapter triggers efficient item animations within your RecyclerView object.

Diffing using a different adapter type

If you choose not to inherit from PagedListAdapter—such as when you're using a library that provides its own adapter—you can still use the Paging Library adapter's diffing functionality by working directly with an AsyncPagedListDiffer object.

Provide placeholders in your UI

In cases where you want your UI to display a list before your app has finished fetching data, you can show placeholder list items to your users. The PagedList handles this case by presenting the list item data as null until the data is loaded.

Placeholders have the following benefits:

  • Support for scrollbars: The PagedList provides the number of list items to the PagedListAdapter. This information allows the adapter to draw a scrollbar that conveys the full size of the list. As new pages load, the scrollbar doesn't jump because your list doesn't change size.
  • No loading spinner necessary: Because the list size is already known, there's no need to alert users that more items are loading. The placeholders themselves convey that information.

Before adding support for placeholders, though, keep the following preconditions in mind:

  • Requires a countable data set: Instances of DataSource from the Room persistence library can efficiently count their items. If you're using a custom local storage solution or a network-only data architecture, however, it might be expensive or even impossible to determine how many items comprise your data set.
  • Requires adapter to account for unloaded items: The adapter or presentation mechanism that you use to prepare the list for inflation needs to handle null list items. For example, when binding data to a ViewHolder, you need to provide default values to represent unloaded data.
  • Requires same-sized item views: If list item sizes can change based on their content, such as social networking updates, crossfading between items doesn't look good. We strongly suggest disabling placeholders in this case.

Provide feedback

Share your feedback and ideas with us through these resources:

Issue tracker
Report issues so we can fix bugs.

Additional resources

To learn more about the Paging Library, consult the following resources.

Samples

Codelabs

Videos

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Last updated 2025年02月10日 UTC.