Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paging library - Boundary callback for network + db with API taking page and size

Short question:

What is the correct way to handle database + network on the Paging library from Architecture components, using an API that uses page + size to load a new page and the BoundaryCallback class?

Research and explanation

Currently the class BoundaryCallback used in the paging library for architecture components, receives as parameter the instance of an element in the list without actual context of where this element is at. It happens in onItemAtFrontLoaded and onItemAtEndLoaded.

My Api is supposed to receive the page and the size of the page to load the next chunk of data. Boundary callback, added as part of the paged list builder, is supposed to tell you when to load the next page of data based on prefetch distance and page size.

Since the Api needs the page number and the size of the page to provide, I don't see a way to send that to the Api just by receiving one of the elements from the list as offered in onItemAtFrontLoaded and onItemAtEndLoaded. Checking the google examples in this link, they use the name of the last element to get the next one, but that doesn't fit an Api with page + size.

They also have another example with only network that uses PagedKeyedDatasource, but there is no sample or clue on how to mix that with the database and the BoundaryCallback.

Edit: Only solutions I have found so far is to store the last loaded page on the shared preferences, but that sounds like a dirty trick.

Refer to https://github.com/googlesamples/android-architecture-components/issues/252#issuecomment-392119468 for official input on it.

like image 765
droidpl Avatar asked May 21 '18 21:05

droidpl


People also ask

How does a pagingsource implementation work?

A PagingSource implementation (for example, one generated by Room) handles loading cached data from the database into the UI. The first step is to use the Room persistence library to define a database that holds a local cache of paged data from the network data source.

How to determine which key to load next in pagingstate?

Determine which key to load next by querying the remote key table instead of using PagingState. Insert or store the returned remote key from the network data source in addition to the paged data itself.

What is the difference between a pagingsource and a remotemediator?

A PagingSource still loads the data; but when the paged data is exhausted, the Paging library triggers the RemoteMediator to load new data from the network source. The RemoteMediator stores the new data in the local database, so an in-memory cache in the ViewModel is unnecessary.


1 Answers

The documentation has this to say on the issue:

If you aren't using an item-keyed network API, you may be using page-keyed, or page-indexed. If this is the case, the paging library doesn't know about the page key or index used in the BoundaryCallback, so you need to track it yourself. You can do this in one of two ways:

Local storage Page key

If you want to perfectly resume your query, even if the app is killed and resumed, you can store the key on disk. Note that with a positional/page index network API, there's a simple way to do this, by using the listSize as an input to the next load (or listSize / NETWORK_PAGE_SIZE, for page indexing). The current list size isn't passed to the BoundaryCallback though. This is because the PagedList doesn't necessarily know the number of items in local storage. Placeholders may be disabled, or the DataSource may not count total number of items.

Instead, for these positional cases, you can query the database for the number of items, and pass that to the network.

In-Memory Page key

Often it doesn't make sense to query the next page from network if the last page you fetched was loaded many hours or days before. If you keep the key in memory, you can refresh any time you start paging from a network source. Store the next key in memory, inside your BoundaryCallback. When you create a new BoundaryCallback when creating a new LiveData/Observable of PagedList, refresh data. For example, in the Paging Codelab, the GitHub network page index is stored in memory.

And links to an example Codelab: https://codelabs.developers.google.com/codelabs/android-paging/index.html#8

like image 66
Luke Avatar answered Sep 26 '22 02:09

Luke