FLORINA MUNTENESCU: Many apps work with large sets of data,
but only need to load and display
a small portion at any given time.
If you're not careful, you might request
data you don't actually need, wasting your user's battery
and bandwidth.
If the data you are displaying is constantly updating,
it can be difficult to keep your UI in sync
and still send only a small amount of information
over the network.
The Paging Library-- part of Jetpack--
tackles these problems, enabling you to load data
gradually and gracefully.
The library supports both large but bounded lists,
as well as lists of unbounded sites,
such as continuously-updating feeds.
It offers integration with RecyclerView,
which is typically used to display large data sets
and plays nicely with either LiveData or RxJava
for observing new data in your UI.
The paging library is based on the idea of sending lists
to the UI with the live data of a list that is observed
by the RecyclerView adapter.
It then builds up on this idea by adding paging
so you can load content gradually.
Let's go over the main components of the library,
and see how they fit in your app's architecture.
The core elements in the Paging Library
are the PagedList and the DataSource.
A PagedList is a collection that loads data in chunks,
known as pages, asynchronously.
A DataSource is the base class for loading snapshots of data
into a give page list.
Data sources can be backed by the network, database, file,
or anywhere you want to retrieve data from.
You create the DataSource using a DataSource.Factory object.
The Paging Library also provides a PagedListAdapter
which helps you present data from PagedList
in a RecyclerView.
The PagedListAdapter is notified when pages are loaded,
and it uses DiffUtil to compute fine grain updates
as new data is received.
The Paging Library provides the LivePagedListBuilder class
for getting a LiveData object of type PagedList.
To create a LivePagedListBuilder,
pass in the dataSourceFactory object and a paging
configuration.
If you prefer working with RxJava instead of LiveData,
then just use the RxPagedListBuilder.
It's constructed similarly to LivePagedListBuilder,
but instead of a live data object,
it will return an observable or flowable
depending on what you need.
Let's take a look at some common scenarios of loading data
from a database or a retrofit-based network source,
and see how the Paging Library helps.
So, first case, let's say that the database
is your DataSource.
The Room Persistence library provides native support
for Paging Library data sources.
For a given query, Room allows you
to return a DataSource.Factory from the Dao,
and handles the implementation of the DataSource for you.
Second case.
Let's say that the database is a cache
for data loaded from network.
So here you would still return a DataSource.Factory
from the Dao, but you will also need
to implement another paging component, a boundary callback.
The boundary callback loads more data
when the user gets near the end of the data that's
in the local cache.
After the data is inserted, the paging library automatically
updates the UI.
But don't forget to associate the boundary callback
with the live PagedListBuilder you created earlier.
That way it can be used by the PagedList.
Third case.
Having only the network as your DataSource.
Here you will have to create both your DataSource
and your DataSource.Factory.
But when choosing which data source type to extend,
consider what your backend API looks like.
If you need to request data from your backend based on a key,
you will extend from ItemKeyedDataSource.
Let's take an example.
You might need to get the first 100
comments added to a GitHub repository
after a certain date.
Then the date will be the key for your DataSource.
ItemKeyedDataSource allows you to define
how to load the initial page, as well
as how to load items both after and before a keyed entry.
If your backend exposes APIs that work with pages,
then you would extend from PageKeyedDataSource.
For example the search repositories GitHub API
returns paginated items.
In the GitHub API request, you need
to specify the query, which page you want,
and optionally, the number of items per page.
And dependent on how you create your network data source,
you will need to implement a DataSource.Factory that knows
how to create your data source.
For full examples of how to implement all of these cases,
including how to handle error cases or retry mechanisms,
check out our samples on GitHub.
OK, let's sum it up.
Here's what you'll need to do to integrate paging.
You'll need to define your DataSource,
create a boundary callback if it's needed,
create a LiveData of a PagedList with the help
of a LivePagedListBuilder, update your adapter
to be a PagedListAdapter, and then finally observe
the LiveData a PagedList in your UI,
and send the PagedList to your adapter.
That's it.
Just five steps.
Check out our documentation, code samples, and collab,
and start using the Paging Library
to provide smooth-performing lists for your users.