首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >分页3-如何处理自beta01以来出现的旧的APPEND RemoteMediator请求?

分页3-如何处理自beta01以来出现的旧的APPEND RemoteMediator请求?
EN

Stack Overflow用户
提问于 2021-02-12 17:44:54
回答 1查看 520关注 0票数 2

从分页3的beta01版本开始,当从RemoteMediator刷新PagingData时,有时会发生上一代的旧APPEND请求在刷新完成后仍在执行的情况。这似乎是从this commit读取的预期行为。当这种情况发生时,旧的APPEND请求调用RemoteMediatorload方法,但使用了过时的PagingState。如果我们在load函数中使用其中的信息,这个过时的PagingState可能会导致错误和崩溃(例如,下面的代码片段使用lastItemOrNull在数据库中查找项的RemoteKeys )。这种破坏性的更改(也破坏了corresponding codelab)在发行说明中根本没有提到。我们应该如何处理这种情况?

下面是一个与beta01断开的RemoteMediator示例。getRemoteKeyForLastItem方法可以返回null (因为旧的PagingState正在查找在前一个REFRESH中删除的数据库条目),从而导致抛出InvalidObjectException

代码语言:javascript
运行
复制
private const val GITHUB_STARTING_PAGE_INDEX = 1

@OptIn(ExperimentalPagingApi::class)
class GithubRemoteMediator(
        private val query: String,
        private val service: GithubService,
        private val repoDatabase: RepoDatabase
) : RemoteMediator<Int, Repo>() {

    override suspend fun load(loadType: LoadType, state: PagingState<Int, Repo>): MediatorResult {

        val page = when (loadType) {
            LoadType.REFRESH -> GITHUB_STARTING_PAGE_INDEX
            LoadType.PREPEND -> return MediatorResult.Success(true)
            LoadType.APPEND -> {
                // this can run with an outdated PagingState from the previous RemoteMediator instance, causing the Exception to be thrown
                val remoteKeys = getRemoteKeyForLastItem(state)
                if (remoteKeys == null || remoteKeys.nextKey == null) {
                    throw InvalidObjectException("Remote key should not be null for $loadType")
                }
                remoteKeys.nextKey
            }

        }

        val apiQuery = query + IN_QUALIFIER

        try {
            val apiResponse = service.searchRepos(apiQuery, page, state.config.pageSize)

            val repos = apiResponse.items
            val endOfPaginationReached = repos.isEmpty()
            repoDatabase.withTransaction {
                if (loadType == LoadType.REFRESH) {
                    repoDatabase.remoteKeysDao().clearRemoteKeys()
                    repoDatabase.reposDao().clearRepos()
                }
                val prevKey = if (page == GITHUB_STARTING_PAGE_INDEX) null else page - 1
                val nextKey = if (endOfPaginationReached) null else page + 1
                val keys = repos.map {
                    RemoteKeys(repoId = it.id, prevKey = prevKey, nextKey = nextKey)
                }
                repoDatabase.remoteKeysDao().insertAll(keys)
                repoDatabase.reposDao().insertAll(repos)
            }
            return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
        } catch (exception: IOException) {
            return MediatorResult.Error(exception)
        } catch (exception: HttpException) {
            return MediatorResult.Error(exception)
        }
    }

    private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, Repo>): RemoteKeys? {
        return state.pages.lastOrNull() { it.data.isNotEmpty() }?.data?.lastOrNull()
                ?.let { repo ->
                    repoDatabase.remoteKeysDao().remoteKeysRepoId(repo.id)
                }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2021-02-13 18:24:26

我和Dustin Lam和Yigit Boyar谈过了,显然,处理这个问题的最好方法是让prepend append不依赖于PagingState。这意味着我们应该将远程键存储在与查询相关的表中,而不是存储在项级别上。

示例:

代码语言:javascript
运行
复制
@Entity(tableName = "search_query_remote_keys")
data class SearchQueryRemoteKey(
    @PrimaryKey val searchQuery: String,
    val nextPageKey: Int
)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66169509

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档