[MUSIC PLAYING]
TJ DAHUNSI: Welcome back.
Last time around, we talked about paging from the database
as a single source of truth and how the remote mediator makes
it possible.
We also show how to monitor the loading states of the Pager
using the load state's flow exposed from the paging
adapter.
With the fundamentals of the Paging library covered,
let's go over some operations we can perform on the data page
through--
specifically, transformations.
It is unlikely the data pulled from the PagingSource
is ready to be bound to the UI as it's fetched.
There usually needs to be a few things added
for additional context, ranging from metadata,
like separators, to additional fields in the list item model
class.
Fortunately, the Paging library provides us
with the ability to map, filter, and perform
other transformations to help create the models the UI needs
to render fully.
Let's get into an example.
In the project we've been working on,
we fetch repositories and display them in the flat list.
This is functional, but can be improved from a presentation
perspective by sectioning the list
to give a user a better sense of placement
in the infinite data set.
A great way to section the repositories
is by grouping them by how many stars they've received.
We can do this by inserting a separator
between consecutive items in the list to have a star count
boundary between them.
We start by operating on a stream of PagingData.
The PagingData type exposes transformation methods
directly.
In our case, we first map the raw repo type
to the UiModel type.
From the newly transformed pagingData of repo items,
we can then insert separators between them.
The insertSeparators method gives us
access to consecutive items of the list,
allowing us to place separators where they might be needed.
Let's revisit our app and its functionality.
The app lets users perform a freeform
search for repositories that match their query.
Since each distinct query fetches a distinct set
of items, each query will need a PagingSource that supports it.
This is an important point.
A Pager is a class that loads data incrementally
from a PagingSource, and therefore
is wholly dependent on its PagingSource for the manner
in which the data is presented.
For query-based PagingSources, significant changes
to the query, likely searches in this case,
will need a new Pager.
Other examples of this scenario include changing sort order
of items, filtering really large queries on the database level,
and so on.
Remember, a Pager is a window into a set of ordered data.
If a new query does not match the original order,
you should create a new Pager.
Check out episode one of this series for a quick refresher
on how.
Finally, throughout this series, we've
been using the Paging data adapter
to display paginated items in the UI.
However, this isn't strictly necessary,
as the Paging library allows you to bring
your own RecyclerView.Adapter.
This is achieved with the AsyncPagingDataDiffer
and it's what the PagingDataAdapter
uses internally.
The AsyncPagingDataDiffer exposes the load state flow,
the item count, a refresh method, a retry method,
and much more.
If you find yourself needing more flexibility
or customization, the AsyncPagingDataDiffer
offers a fantastic way to take advantage
of most of the abilities and conveniences of the Paging
library through delegation.
It is always worth taking a look at the source
of the PagingDataAdapter to see how it delegates
to the AsyncPagingDataDiffer as a starting point
on your own exploration.
That's it for this "MAD Skills" series on the Paging library.
In this episode, we covered transformations PagingData
offers, discussed the Pager's dependency on its PagingSource,
highlighted scenarios that require a new Pager
to be created, presented an overview
of the AsyncPagingDataDiffer, and shown
how it can be used to bring your own RecyclerView.Adapter.
Thanks for tuning into this "MAD Skills" series
on the Paging library.
We've got so much more great stuff coming your way.
So keep tuned and we'll catch you in the next one.
[MUSIC PLAYING]