How to implement PagingSource.getRefreshKey for cursor based pagination - Android Jetpack Paging 3
Asked Answered
R

1

8

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.

Rena answered 25/5, 2021 at 16:19 Comment(1)
Did you find a solution? I'm with the same problemCasket
I
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
    }
}
Ifc answered 11/8, 2021 at 11:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.