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

2024-06-23

自版本以来beta01的 Paging 3,当从 a 刷新 PagingData 时RemoteMediator,有时会发生旧的APPEND刷新完成后,仍会执行上一代的请求。这似乎是预期的行为这次提交 https://android.googlesource.com/platform/frameworks/support/+/e754df9ed34341e5aa71e26427244951089e854b%5E%21/paging/common/src/main/kotlin/androidx/paging/RemoteMediatorAccessor.kt?fbclid=IwAR1ED_0_f-1KFQy0TXCnmWvihBTh8SsTY4EaygzKM-90NhZ2i7J9jCvxE00。 当这种情况发生时,老APPEND请求调用RemoteMediator's load方法但过时了PagingState。这个过时的PagingState如果我们在加载函数中使用其中的信息,可能会导致错误和崩溃(例如,下面的代码片段使用lastItemOrNull找到RemoteKeys对于数据库中的项目)。这一重大变化(也打破了对应的Codelab https://developer.android.com/codelabs/android-paging#19)在发行说明中根本没有提及。我们应该如何处理这个问题?

这是一个 RemoteMediator 的示例,它与beta01. The getRemoteKeyForLastItem方法可以返回null(因为旧PagingState正在查找先前删除的数据库条目REFRESH)导致InvalidObjectException被扔掉。

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)
                }
    }
}

我与 Dustin Lam 和 Yigit Boyar 进行了交谈,显然,处理此问题的最佳方法是在前面添加一个附加项,而不依赖于PagingState。这意味着我们应该将远程密钥存储在与查询相关的表中,而不是存储在项目级别上。

Exmaple:

@Entity(tableName = "search_query_remote_keys")
data class SearchQueryRemoteKey(
    @PrimaryKey val searchQuery: String,
    val nextPageKey: Int
)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Paging 3 - 如何处理自 beta01 以来出现的旧 APPEND RemoteMediator 请求? 的相关文章

  • 获取 ES6 符号的描述

    我想知道是否有一种很好的方法来获取符号的描述 例如 var s Symbol 5 toString 的默认实现将简单地打印 符号 5 我想找到一种方法来提取实际描述 即 5 Symbol description https develope
  • C# 如何更改 windows.forms.listview 中的网格线颜色

    如何更改 windows forms listview 中的网格线颜色 我认为没有办法在不覆盖 Paint Event 的情况下在列表视图上执行此操作 但是 如果您能够切换到网格视图 您可以这样做 this dataGridView1 Gr
  • 添加标签以绘制 R 中的特定值

    我使用以下数据集创建一个图 并且我想仅为 DisplayName 列中标有 T 的点添加标签 Probe Name DisplayName X Y bob1 A 0 53 989643 7935 185 bob2 B T 55 11423
  • Android:getIntent() 已弃用

    我的程序由一个 MainActivity 和两个片段活动组成 我需要一个片段从用户那里获取一个字符串值并将其传递给第二个片段 我正在努力思考如何做到这一点 由于我熟悉意图 我发现这个答案 https stackoverflow com qu
  • 使用多处理或线程加速单个任务

    是否可以使用多处理 线程来加速单个任务 我的直觉是答案是否定的 以下是我所说的 单一任务 的示例 for i in range max pick random choice on off both 当参数为 10000000 时 在我的系统
  • 配置 SourceTrail 以接受带有 @ 语法的嵌入式 c/c++ 头文件

    我正在尝试使用 Sourcetrail https www sourcetrail com https www sourcetrail com 快速了解 pic18 系列微控制器的一些旧嵌入式 c c 源代码 导入硬件包含文件时出现错误 该
  • 在 PowerShell 中更改错误消息语言

    我正在尝试在 powershell 中以英文显示错误 以便我可以更轻松地在线搜索它们 当出现错误时 它会以法语显示 如下所示 PS C Users Olivier lpthw gt type nul gt ex2 py type Impos
  • 从 Google 地图中的纬度、经度搜索生成英国邮政编码

    我正在尝试通过 Google 地图中的纬度和经度搜索生成英国邮政编码 例如 在 Google 地图中搜索 57 350237 1 977539 将返回以下内容 https i stack imgur com mSULM png https
  • UIProgressView 没有更新?

    我已经开始在 iOS5 中使用 UIProgressView 但还没有真正使用它 我在更新视图时遇到问题 每次更新进度后 我都有一组连续的操作 问题是 进度视图不是一点一点更新的 而是在全部完成之后才更新 事情是这样的 float cnt
  • 如何使用元类中的方法更改 groovy 中方法的行为

    我想通过以下方式 破坏 Groovy 中的 plus 方法 Integer metaClass plus Integer n gt delegate n 1 assert 2 2 5 我收到 StackOverflowException 这
  • HTTPS文件下载C#

    我需要下载隐藏在 HTTPS 连接后面的文件 我对下载安全网站后面的文件不熟悉 我尝试使用凭据来解决此问题 但无济于事 据我所知 您需要创建并使用证书来完成此操作 但我没有找到任何示例 任何帮助表示赞赏 这就是我现在所拥有的 WebClie
  • 带骨干的递归函数jquery

    我在主干中有一个应用程序 我想在 Json 中找到一些记录并打印出来 我的 JSON 是这样的 id r1 hotel id 1 name Single level 1 id r1 1 hotel id 1 name Double leve
  • 无法将 Angular 更新到版本 6

    我正在尝试将角度更新到最新版本 我已经更新了全局 angular cli npm install g angular cli 然后当我尝试使用更新本地 angular cli 时ng update angular cli我收到此错误 Err
  • 使用协处理器HBase创建二级索引

    我一直在尝试编写自己的协处理器 使用 prePut 挂钩创建二级索引 首先 我只是尝试让 prePut 协处理器工作 到目前为止 我可以将协处理器添加到传递给它的 put 对象中 我发现我无法让协处理器写入与传入的 put 对象正在写入的行
  • 可以使用 libSegFault.so 获取 SIGABRT 的回溯吗?

    神奇的咒语 LD PRELOAD lib libSegFault so someapp runs someapplibSegFault so 提供有关 SIGSEGV 的回溯信息 如中所述many http blogs fau de wit
  • 正确使用 GuzzleHttp/Psr7/Response

    不确定在 php 页面中显示 Psr7 Guzzle Response 的正确方法是什么 现在 我正在做 use GuzzleHttp Psr7 BufferStream use GuzzleHttp Psr7 Response class
  • 为什么对于某些数组 A,sizeof(A) 在函数内不起作用? [复制]

    这个问题在这里已经有答案了 下列 include
  • 从 pexpect 中提取 stderr

    我的问题很简单 我可以吗 expect 使用 pexpect 查看 stderr 上的某些输出 它似乎pexpect spawn 只能用于期望 stdout 上的输出 乌托邦的例子 import pexpect child pexpect
  • Python 内存使用情况

    因此 我有一些代码接收一组文件 将其可以缝合在一起 然后绘制它们 我发布了大部分代码 试图使其更具可读性 如果需要 可以添加更多代码 for paths dirs files in os walk start path for d in d
  • 更新 Android Studio 后 Android 模拟器无法运行

    我通常使用 Android Studio 从 2 2 3 更新到 2 3 后 我的模拟器不再工作 这也很困难 因为 Google 决定弃用独立 SDK 管理器 我发现我可以检查 选择 显示包详细信息 但我仍然无法让我的 Google And

随机推荐

  • 如何将枚举绑定到 playframework 表单?

    我有一个以下形式的枚举 object MatchFilterType extends Enumeration type MatchFilterType Value val gt Value gt val lt Value lt val eq
  • TensorFlowdynamic_rnn 回归器:ValueError 维度不匹配

    我想构建一个用于回归的玩具 LSTM 模型 This http mourafiq com 2016 05 15 predicting sequences using rnn in tensorflow html不错的教程对于初学者来说已经太
  • 如何使用java sdk创建AWS Elastic Beanstalk环境?

    任何人都可以帮助我或提供任何资源来使用 java 程序创建 Aws Elastic beanstalk 环境并在其中部署我们的应用程序吗 先感谢您 您可以下载 AWS Java SDKhere http aws amazon com sdk
  • 如何选择PyQt的图形工具包

    我正在为我的客户开发一个 PyQt 应用程序 问题是我的默认图形是 Gnome 而我的客户端是 KDE 所以有些差异是我无法控制的 如何强制 pyQt 选择良好的图形系统 Gnome 而不是默认系统 KDE Use QApplication
  • List.Enumerator IEnumerator.Reset() 方法实现

    尽管事实如此 IEnumerator Reset永远不应该使用方法 https stackoverflow com a 5968973 1163867我发现方法实现的奇怪行为List
  • MsgBox 和 MessageBox.Show 有区别吗?

    以下两者有区别吗 msgbox messagebox show 有些教程使用 msgbox 有些教程使用另一个 messagebox show 我看到两者都可以有可编辑的样式 但我想知道 为什么有两个 是为了适应老程序员 他们学习过旧版本的
  • 对多维数组的键进行递归排序

    我很难尝试对多维数组的键进行递归排序 我尝试过usort 但没有成功 样本数据 first level gt dir 3 gt subdir 1 gt file 2 mp4 gt object name gt file 2 mp4 file
  • Git 将合并恢复到特定父级

    我有一个 git 存储库 但在恢复合并时遇到问题 当前哈希为 0ce2ca0b35f59af267241cf4d40d16a3e13ba6f3 它有两个父母 df1acf5f54426d30f12c6b4558c3dd922297aae3
  • flink 连接被对等方重置

    我有一个 Flink Streaming 作业 它失败了 我得到如下日志 有人能告诉我如何解决这个问题吗 有时运行一天后失败 有时运行几个小时后失败 09 30 25 948 INFO org apache flink runtime ex
  • 在轴顶部绘制标记

    我正在尝试使用 numpy 制作 x y 散点图 现在 轴从 0 0 开始并延伸以与数据范围对齐 我需要绘制位于 x 0 线上的两个点 目前看来 符号是在轴之前绘制的 随后被轴截断 我希望它出现在轴的顶部 我相信我可以用 标签 做一些事情
  • 关于通过字符类进行子集化的快速问题

    我认为这是一件非常快的事情 但我想我会问 因为我一辈子都不记得该怎么做 假设 我有一个 data frame 称之为 DF 具有以下标题 Blah Bleh and Meh 我还有一个字符类向量foo 其元素与标题相同DF Blah lt
  • 文本周围有黑线

    如何在我的textView 的文本周围制作黑线 上图示例 扩展 TextView 类 然后在onDraw中 先使用黑色绘制文本 然后再次绘制 稍微小一点并使用白色 为了获得额外的 正确性 请向 XML 添加自定义属性以设置 周围的 线 颜色
  • 是否可以将环境变量添加到 MongoDB 配置文件中?

    我正在使用 YAML 语法配置 MongoDB 副本集 但是 我想使用 MONGODB HOME 环境变量指向数据库 storage dbPath ENV MONGODB HOME data db 我尝试过使用 等 但没有成功 可以这样做吗
  • 安装 Joomla 时出错

    在我的本地 xampp 中安装并配置 Joomla 1 5 CMS 我安装完之后 当我访问 Joomla 网站时 它显示一些错误消息 Strict Standards Non static method JLoader import sho
  • Intellij Idea可以自动阶段更改吗

    经过几天的任务处理后 我决定看看已经完成了哪些工作git status来自 Git Bash 有些文件在Changes to be committed list 有些在Changes not staged for commit 有趣的是 我
  • Hibernate 4.2,双向@OneToOne 和@Id

    我正在尝试使用OneToOne添加可选数据的关系 ExtraData 到主类 MainItem 的所有实例ExtraData应该链接到一个实例MainItem 但并非所有实例MainItem需要有一个实例ExtraData 我主要对单向关系
  • 安装时 Chrome 扩展显示 CRX_REQUIRED_PROOF_MISSING

    我刚刚创建了一个供公司内部使用的 chrome 扩展 我不想发布它 而是想传递给我的同事 当我将该扩展打包到本地 chrome 中时 它给了我错误消息 CRX REQUIRED PROOF MISSING 您无法分发 Chrome 扩展程序
  • 如何在磁盘或数据库上存储稀疏可查询矩阵?

    我需要在磁盘上存储稀疏矩阵 它就像一个拥有数百万行和数千列的数据库表 其中许多或大多数列为空 它需要是可查询的 就像在某些列上带有 WHERE 的 SQL SELECT 一样 我的具体要求是Java 我首先想到使用Java 版 Berkel
  • 防止某些孩子影响 MouseEvent hitbox

    我有一个影片剪辑 用作按钮 在该影片剪辑中 当鼠标悬停在按钮上时会显示一个大阴影 我的问题是 这个阴影会影响鼠标悬停 并导致 mouseOver 和 mouseOut 事件的 捕获 区域比我想要的大得多 我尝试过禁用该子项上的鼠标事件以及我
  • Paging 3 - 如何处理自 beta01 以来出现的旧 APPEND RemoteMediator 请求?

    自版本以来beta01的 Paging 3 当从 a 刷新 PagingData 时RemoteMediator 有时会发生旧的APPEND刷新完成后 仍会执行上一代的请求 这似乎是预期的行为这次提交 https android googl