Introduction to Paging 3.0 in the MAD Skills Series | by TJ | Android Developers | Oct, 2021


Welcome to the Paging 3.0 MAD Skills series! In this article I’ll be introducing Paging 3.0 and highlighting how to integrate it into the data layer of your application. Want to watch and read? Check out the video for this episode here!

Paging MAD Skills episode 1

If you’re currently using Paging 2.0, Paging 3.0 offers a bunch of improvements over its predecessor including:

  • First-class support for Kotlin coroutines and Flow.
  • Support for async loading using RxJava Single or Guava ListenableFuture primitives.
  • Built-in load state and error signals for responsive UI design, including retry and refresh functionality.
  • Improvements to the repository layer, including cancellation support and a simplified data source interface.
  • Improvements to the presentation layer, list separators, custom page transforms, and loading state headers and footers.

Be sure to check out the Paging 2.0 to Paging 3.0 migration guide for more information.

Dropping it in

A PagingSource, similar to a Map, is defined by two generic types: that of its paging key, and that of the data loaded. For example, the declaration of a PagingSource that fetched Repo items from the page based Github API would be defined as:

PagingSource definition

The PagingSource needs to implement 2 abstract methods to be fully functional:

  1. load()
  2. getRefreshKey()
  • Key of the page to be loaded: If this is the first time that load is called (initial load), the LoadParams.key will be null. In this case, you will have to define the initial page key.
  • Load size: the requested number of items to load.

The return type of load is a LoadResult. It can either be:

  • LoadResult.Page: for successful loads.
  • LoadResult.Error: for when errors arise.
load implementation

Note that by default, the initial load size is 3 * page size. This ensures that the first time the list is loaded the user will see enough items without triggering too many network requests if the user scrolls a bit. This is also something to consider when computing the next key in the PagingSource implementation.

getRefreshKey implementation

The second thing needed to construct a Pager is the PagingConfig which defines parameters that govern how the Pager will fetch data. It exposes quite a few optional arguments that let you fine tune the Pager’s behavior, however the pageSize argument is required.

Creating a Pager

A brief description of the arguments utilized in the construction of the PagingConfig above follows:

  • pageSize: The number of items to be loaded at once from the PagingSource.
  • enablePlaceholders: Whether the PagingData returns null for items that haven’t been loaded yet.

We typically want the pageSize to be large enough (at least enough to fill the visible area of the screen, but preferably 2–3x that) so the Pager doesn’t have to keep fetching data over and over again to show enough material on the screen as the user scrolls.

Since a PagingSource is a snapshot that changes when the PagingSource is invalidated, the Paging Library offers multiple ways of consuming PagingData as a stream including:

  • Kotlin Flow via Pager.flow
  • LiveData via Pager.liveData
  • RxJava Flowable via Pager.flowable
  • RxJava Observable via Pager.observable

This stream of PagingData is what the ViewModel can then opt to transform before presenting the paged items to the UI.

Source link

Latest articles

Related articles

Leave a reply

Please enter your comment!
Please enter your name here