2

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
}
M Rajoy
  • 4,028
  • 14
  • 54
  • 111
  • see `LivePagedListBuilder` (or `PagedListBuilder`) – pskink Sep 17 '19 at 10:57
  • @pskink this is what I've used through the toFlowable extension (check edited question) – M Rajoy Sep 17 '19 at 12:03
  • Still dont know how to request more pages though :( – M Rajoy Sep 17 '19 at 12:04
  • you have to call `build()` and when you have `PagedList` object simply use `loadAround()` / `get()` methods, if still uncertain see `PagedListAdapterHelper.java` source file and check `mList` field and where it is used - [PagedList](https://developer.android.com/reference/android/arch/paging/PagedList) official docs say: *"A PagedList is a List which loads its data in chunks (pages) from a DataSource. Items can be accessed with get(int), and further loading can be triggered with loadAround(int)."* – pskink Sep 17 '19 at 12:21
  • @pskink this does work, thanks. – M Rajoy Sep 17 '19 at 15:04
  • sure, your welcome – pskink Sep 17 '19 at 15:25

1 Answers1

0

Use Marker clustering that handles the display of a large number of points in google map check android-maps-utils sample

Vinoth M
  • 91
  • 2
  • 4
  • I am already using cluster rendering, which does not work very well with these amounts of places (5k makes it very slow), but that is a rendering issue, whilst I am talking about data retrieval issue. – M Rajoy Sep 17 '19 at 12:15