Pagination Using Android Jetpack

Kapil Vij
3 min readSep 11, 2021

--

Paging Library helps you fetch loads of data from Network or from local source effectively and efficiently.

Conventional way requires us to look for below parameters to do it effectively:

  • Keeping track of “keys”
  • Requesting correct next page
  • And preventing duplicate network requests
  • Tracking loading state i.e “load more”

Paging3 Android got you covered here :)

Library Architecture:

Repository Layer

  • PagingSource loads data from any single source among network and local data source.
  • RemoteMediator handles paging from layered data source like combination of network datasource with local data cache.

ViewModel Layer

  • Pager component provides public API for creating PagingData instance which is retrieved based on PagingSource object and PagingConfig object.
  • Pager supports flow for coroutines, flowable/observable for Rx and livedata out of the box.
  • PagingConfig allows you to set several parameters among which pageSize in mandatory and represents numbers of items to load from paging source at a time.

UI Layer

  • PagingDataAdapter is a RecyclerView adapter that handles paginated data and is a primary component in this layer.
  • The PagingDataAdapter listens to internal PagingData loading events as pages are loaded and uses DiffUtil on a background thread to compute fine-grained updates as updated content is received in the form of new PagingData objects.

Let’s Start Coding:

Add below line to your module level build.gradle file under dependencies

implementation "androidx.paging:paging-runtime:3.0.1"

Creating a PagingSource requires below items:

  • The type of the paging key — which is used retrieve next data like pageNum.
  • The type of data loaded — Response entity that we source will supply
  • Where is the data retrieved from i.e. Network Source or Local data source
class SamplePagingSource : PagingSource<Int, DataModel>()  {
override fun getRefreshKey(state: PagingState<Int, DataModel>): Int? {
TODO("Not yet implemented")
}

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, DataModel> {
TODO("Not yet implemented")
}
}

The load() function is called by the Paging library to asynchronously fetch more data as user scrolls and returns a LoadResult which could be LoadResult.Page if success or LoadResult.Error in case of error. The LoadParams object keeps information related to the load operation.

By default, the initial load size is 3 * page size. That way, Paging ensures that the first time the list is loaded the user will see enough items and doesn’t trigger too many network requests, if the user doesn’t scroll past what’s loaded.

Below is sample code for repository:

class SampleRepository(private val service: SampleService) {

fun getDataStream(query: String): Flow<PagingData<DataModel>> {
return Pager(
config = PagingConfig(
pageSize = NETWORK_PAGE_SIZE,
enablePlaceholders = false
),
pagingSourceFactory = { SamplePagingSource(service, query) }
).flow
}

companion object {
const val NETWORK_PAGE_SIZE = 50
}
}

Refer below for ViewModel code:

class SampleViewModel(
...
) : ViewModel() {

override fun onCleared() {
...
}

private fun fetchData(): Flow<PagingData<DataModel>> =
repository.getDataStream().cachedIn(viewModelScope)
}

Flow<PagingData> has a handy cachedIn() method that allows us to cache the content of a Flow<PagingData> in a CoroutineScope. Since we're in a ViewModel, we will use the androidx.lifecycle.viewModelScope.

Note: If you’re doing any operations on the Flow, like map or filter, make sure you call cachedIn after you execute these operations to ensure you don't need to trigger them again.

Make your adapter understand PagingData by extending your list adapter by PagingDataAdapter which is very similar to RecyclerView.Adapter as shown in below code.

class SampleAdapter : PagingDataAdapter<Key, SampleViewHolder>(DATA_COMPARATOR) {
// TODO : Add Body
}

Paging 3.0 does lot for us under the table

  • Handles in-memory cache.
  • Requesting data when users is about to reach end of list.

References

https://developer.android.com/topic/libraries/architecture/paging/v3-overview

https://developer.android.com/codelabs/android-paging

https://www.youtube.com/watch?v=1cwqGOku2a4

--

--