I have a database of around 5000 "places" (that is, lat and lon to be displayed on a map), and I want to be able to display them in a map.
Now retrieving 5000 places in one go from Room is giving me trouble (exceeds the size limit as stated in this question), so I'd like to use the paging library to retrieve batches of around 100 and populate the map slowly.
However it seems the Paging library coming with Jetpack is heavily geared towards using it with a RecyclerView, the entire documentation revolves around building a endless scrolling recyclerview.
So I was wondering if it's possible to use it with custom components and not exclusively with a PagedAdapter as stated in the documentation. They mention AsyncPagedListDiffer which has this signature:
AsyncPagedListDiffer(ListUpdateCallback listUpdateCallback, AsyncDifferConfig<T> config)
So I went on and tried implementing this like so:
DAO:
@Query("SELECT * FROM places join list_results where places.placeId = list_results.id ORDER by placeName ASC")
abstract fun getFilteredPlacesPaginated(): DataSource.Factory<Int, PlaceVO>
Repository:
override fun getListPlaces(pageSize: Int, boundaryCallback: PagedList.BoundaryCallback<StateAwarePlace>): Flowable<PagedList<StateAwarePlace>> {
return placesDao.getFilteredPlacesPaginated().map { StateAwarePlace.state(it) }.toFlowable(pageSize = pageSize, boundaryCallback = boundaryCallback)
}
ViewModel:
val boundaryCallback: PagedList.BoundaryCallback<StateAwarePlace> = object : PagedList.BoundaryCallback<StateAwarePlace>() {
override fun onZeroItemsLoaded() {
super.onZeroItemsLoaded()
Timber.w("PAGINATEDLIST - OnZeroItemsLoaded")
}
override fun onItemAtEndLoaded(itemAtEnd: StateAwarePlace) {
super.onItemAtEndLoaded(itemAtEnd)
Timber.w("PAGINATEDLIST - onItemAtEndLoaded ${itemAtEnd.place.placeName}")
}
override fun onItemAtFrontLoaded(itemAtFront: StateAwarePlace) {
super.onItemAtFrontLoaded(itemAtFront)
Timber.w("PAGINATEDLIST - onItemAtFrontLoaded ${itemAtFront.place.placeName}")
}
}
val paginatedPlaces = placesRepository.getListPlaces(50, boundaryCallback).toLiveData()
Fragment:
val asyncPagedListDiffer = AsyncPagedListDiffer<StateAwarePlace>(object : ListUpdateCallback {
override fun onChanged(position: Int, count: Int, payload: Any?) {
Timber.w("PAGINATEDLIST - Item in position $position has changed, now count is $count, payload $payload")
}
override fun onMoved(fromPosition: Int, toPosition: Int) {
Timber.d("PAGINATEDLIST - Item moved from $fromPosition to $toPosition")
}
override fun onInserted(position: Int, count: Int) {
Timber.i("PAGINATEDLIST - Item inserted on position $position, new count is $count")
}
override fun onRemoved(position: Int, count: Int) {
Timber.v("PAGINATEDLIST - Item removed on position $position, count is $count")
}
}, PlacesPaginatedAdapter.asyncConfig);
viewModel.paginatedPlaces.observe(this) { placesList: PagedList<StateAwarePlace> ->
asyncPagedListDiffer.submitList(placesList)
asyncPagedListDiffer.addPagedListListener { previousList, currentList ->
Timber.w("PAGINATEDLIST - Paged list listener ${previousList?.size} to ${currentList?.size}")
}
}
But it seems its always loading the total amount of places.
I also have no clue on how to tell the pagedlist to retrieve more pages, or how to use the differ to send the data to my map instance...
toFlowable:
fun <Key, Value> DataSource.Factory<Key, Value>.toFlowable(
pageSize: Int,
initialLoadKey: Key? = null,
boundaryCallback: PagedList.BoundaryCallback<Value>? = null,
fetchScheduler: Scheduler? = null,
notifyScheduler: Scheduler? = null,
backpressureStrategy: BackpressureStrategy = BackpressureStrategy.LATEST
): Flowable<PagedList<Value>> {
return createRxPagedListBuilder(
dataSourceFactory = this,
config = Config(pageSize),
initialLoadKey = initialLoadKey,
boundaryCallback = boundaryCallback,
fetchScheduler = fetchScheduler,
notifyScheduler = notifyScheduler).buildFlowable(backpressureStrategy)
}
private fun <Key, Value> createRxPagedListBuilder(
dataSourceFactory: DataSource.Factory<Key, Value>,
config: PagedList.Config,
initialLoadKey: Key?,
boundaryCallback: PagedList.BoundaryCallback<Value>?,
fetchScheduler: Scheduler?,
notifyScheduler: Scheduler?
): RxPagedListBuilder<Key, Value> {
val builder = RxPagedListBuilder(dataSourceFactory, config)
.setInitialLoadKey(initialLoadKey)
.setBoundaryCallback(boundaryCallback)
if (fetchScheduler != null) builder.setFetchScheduler(fetchScheduler)
if (notifyScheduler != null) builder.setNotifyScheduler(notifyScheduler)
return builder
}