1
// GitHub page API is 1 based: https://developer.github.com/v3/#pagination
private const val GITHUB_STARTING_PAGE_INDEX = 1

class GithubPagingSource(
        private val service: GithubService,
        private val query: String
) : PagingSource<Int, Repo>() {

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Repo> {
        val position = params.key ?: GITHUB_STARTING_PAGE_INDEX
        val apiQuery = query + IN_QUALIFIER
        return try {
            val response = service.searchRepos(apiQuery, position, params.loadSize)
            val repos = response.items
            val nextKey = if (repos.isEmpty()) {
                null
            } else {
                // initial load size = 3 * NETWORK_PAGE_SIZE
                // ensure we're not requesting duplicating items, at the 2nd request
                position + (params.loadSize / NETWORK_PAGE_SIZE)
            }
            LoadResult.Page(
                    data = repos,
                    prevKey = if (position == GITHUB_STARTING_PAGE_INDEX) null else position - 1,
                    nextKey = nextKey
            )
        } catch (exception: IOException) {
            return LoadResult.Error(exception)
        } catch (exception: HttpException) {
            return LoadResult.Error(exception)
        }
    }
    // The refresh key is used for subsequent refresh calls to PagingSource.load after the initial load
    override fun getRefreshKey(state: PagingState<Int, Repo>): Int? {
        // We need to get the previous key (or next key if previous is null) of the page
        // that was closest to the most recently accessed index.
        // Anchor position is the most recently accessed index
        return state.anchorPosition?.let { anchorPosition ->
            state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1)
                ?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1)
        }
    }

}

This is the code of getRefreshKey function of the paging3 codelab.

I thought that it's just okay to return state.anchorPosition. But why is this returning closestPagetToPosition's previous key plus 1?? This is the link of the paging 3 code lab.

Isaac
  • 11
  • 3
  • I agree with you, for some reason, the library is very bad, and closed source, and really hard to use. The documentation is poorly written, with not covering all cases, or explaining, why things are the way they are. If I had a authority in my company, I would never have used it, but unfortunately, we have to use this terrible library – Pulkit Jun 22 '23 at 02:37

1 Answers1

2

Well, state.anchorPosition is index of the first item you see in this list, getRefreshKey should return the key to load on refresh.

In this example, key is index of page and each page typically contains many items, lets say 20. Now loading two pages would mean using keys 1 and 2 and having 40 items loaded.

In this situation, when you are looking at item on index 30, state.anchorPosition is 30 as well, but you definitely don't want your refresh key to be 30, you need it to be 2 because item on index 30 comes from page 2. This is what closestPageToPosition does.

Jan Bína
  • 3,447
  • 14
  • 16