6

I am trying to implement cursor based pagination (based on GraphQL Relay spec) using Android Paging Library 3, but I don't know how to implement getRefreshKey.

This is what I've tried:

data class PagingKey(
    val before: String? = null,
    val after: String? = null,
)

class MoviePagingSource() : PagingSource<PagingKey, Movie>() {
    override suspend fun load(params: LoadParams<PagingKey>): LoadResult<PagingKey, Movie> {
        return try {
            val response = fetchMovies(
                before = params.key?.before,
                after = params.key?.after,
                pageSize = params.loadSize,
            )

            LoadResult.Page(
                data = response.edges.map { mapEdgeToMovie(it) },
                prevKey = if (response.pageInfo.hasPreviousPage) PagingKey(
                    before = response.pageInfo.startCursor
                ) else null,
                nextKey = if (response.pageInfo.hasNextPage) PagingKey(
                    after = response.pageInfo.endCursor
                ) else null,
            )
        } catch (exception: Exception) {
            LoadResult.Error(exception)
        }
    }

    override fun getRefreshKey(state: PagingState<PagingKey, Movie>): PagingKey? {
        // TODO: What to return here?
    }
}

In all the examples I could find a page number is simply incremented/decremented, but that doesn't work with cursors.

What is the proper way to implement this?


Before this gets incorrectly marked as a duplicate, I've already seen this question. This does not answer my question because their API is called as service.getOrders(query, params.key ?: "", 10) instead of the separate before/after arguments like fetchMovies above.

Duncan Lukkenaer
  • 12,050
  • 13
  • 64
  • 97

1 Answers1

2

What you can do is get the index of the page to be reloaded and then go to the next page to get the prevKey or to the previous page to get the nextKey.

 override fun getRefreshKey(
    state: PagingState<PagingKey, Movie>,
): PagingKey? {
    return state.anchorPosition?.let { anchorPosition ->
        val anchorPageIndex = state.pages.indexOf(state.closestPageToPosition(anchorPosition))
        state.pages.getOrNull(anchorPageIndex + 1)?.prevKey ?: state.pages.getOrNull(anchorPageIndex - 1)?.nextKey
    }
}
cherif
  • 1,164
  • 1
  • 11
  • 16