1

This is my first time using Paging library 3. This is my PagingSource file, For the API we have to use a cursor in order to do paging, every time I refresh the adapter it scrolls back to the top of the list, is there any way to refresh the list without scrolling to the top?

class SearchProductDataSource(
    private val searchFilter: SearchFilter,
    private val searchProductsUseCase: SearchProductsUseCase
) : PagingSource<String, Product>() {

    override fun getRefreshKey(state: PagingState<String, Product>): String? {
        return null
    }

    override suspend fun load(params: LoadParams<String>): LoadResult<String, Product> {
        try {
            val currentKey = params.key
            val newFilter: SearchFilter = searchFilter.copy(afterCursor = currentKey)
            val result = searchProductsUseCase(newFilter, params.loadSize)
            val nextKey = if (result?.pageInfo?.hasNextPage == true)
                result.cursor
            else
                null

            return LoadResult.Page(result.list, currentKey, nextKey)
        } catch (e: Exception) {
            Timber.e(e)
            return LoadResult.Error(e)
        }
    }

}

This is how I call a refresh method after updating the wishlist.

adapter.refresh()
a-rohim
  • 506
  • 1
  • 5
  • 19

1 Answers1

0

You need to implement getRefreshKey to return a non-null result.

getRefreshKey is used by Paging to get the key for refresh, if you return null, that's what will be passed into params.key, which in this case, looks like it returns the first page.

Something similar to the follow may work for you:

override fun getRefreshKey(state: PagingState<String, Product>): String? {
  return state.anchorPosition?.let { anchorPosition ->
    state.closestPageToPosition(anchorPosition)?.let { anchorPage ->
      val pageIndex = pages.indexOf(anchorPage)
      if (pageIndex == 0) {
        null
      } else {
        pages[pageIndex - 1].nextKey
      }
    }
  }
}
dlam
  • 3,547
  • 17
  • 20
  • After adding that code and I don't know why I keep getting this error ``` java.lang.IllegalStateException: The same value, eyJsYXN0X2lkIjo2ODk0NzA5MzA5NjIxLCJsYXN0X3ZhbHVlIjowfQ==, was passed as the prevKey in two sequential Pages loaded from a PagingSource. Re-using load keys in PagingSource is often an error, and must be explicitly enabled by overriding PagingSource.keyReuseSupported. ``` and I overrided keyReuseSupported to true, there is no error, but the list keep refreshing endlessly – a-rohim Oct 11 '21 at 06:23
  • 1
    This error means you are trying to use the same key to load two different pages, this would normally result in infinitely prepending the same page over and over again in a loop. This is happening because you always pass the current key for prevKey, which means that using key "A" for page1, you are telling Paging to use the same key "A" to fetch page 0, and so forth. You need to either pass a valid key or `null` to indicate there is no more data to prepend. – dlam Oct 11 '21 at 20:52
  • 1
    Note that for refresh, because you will be resuming from the middle of the list, you will need to support prepending in some way and can't just always pass `null`. – dlam Oct 11 '21 at 20:53
  • Oh...I didn't know that good to know @dlam thanks. will try to fix accordingly. – a-rohim Oct 12 '21 at 03:03
  • Hey @dlam can you know how to solve this [issue](https://stackoverflow.com/q/69755212/11560810) – Kotlin Learner Oct 28 '21 at 14:03