使用 DiffUtil 在 RecyclerView 上添加拖放

2024-05-16

我有一个从房间数据库更新的列表。我从 Room 收到更新的数据作为新列表,然后将其传递给列表适配器 https://developer.android.com/reference/androidx/recyclerview/widget/ListAdapter's submitList获取更改的动画。

list.observe(viewLifecycleOwner, { updatedList ->
    listAdapter.submitList(updatedList)
})

现在,我想为同一个 RecyclerView 添加拖放功能。我尝试使用它来实现它ItemTouchHelper。但是,那notifyItemMoved()不起作用,因为 ListAdapter 通过以下方式更新其内容submitList().

override fun onMove(
    recyclerView: RecyclerView,
    viewHolder: RecyclerView.ViewHolder,
    target: RecyclerView.ViewHolder
): Boolean {

    val from = viewHolder.bindingAdapterPosition
    val to = target.bindingAdapterPosition

    val list = itemListAdapter.currentList.toMutableList()
    Collections.swap(list, from, to)

    // does not work for ListAdapter
    // itemListAdapter.notifyItemMoved(from, to)

    itemListAdapter.submitList(list)

    return false
}

拖放现在可以正常工作,但只有在缓慢拖动时,当拖动足够快时,我会得到不同且不一致的结果。

这可能是什么原因?为使用 ListAdapter 的 RecyclerView 实现拖放功能的最佳方法是什么?


我最终实现了一个新的适配器并使用它而不是 ListAdapter,如上所述马丁·马可尼尼的回答 https://stackoverflow.com/a/68452428/10833325。我添加了两个单独的函数。一个用于从 Room 数据库接收更新(替换submitList来自 ListAdapter),另一个用于拖动时的每个位置变化

MyListAdapter.kt

class MyListAdapter(list: ArrayList<Item>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    // save instance instead of creating a new one every submit 
    // list to save some allocation time. Thanks to Martin Marconcini
    private val diffCallback = DiffCallback(list, ArrayList())

    fun submitList(updatedList: List<Item>) {
        diffCallback.newList = updatedList
        val diffResult = DiffUtil.calculateDiff(diffCallback)

        list.clear()
        list.addAll(updatedList)
        diffResult.dispatchUpdatesTo(this)
    }

    fun itemMoved(from: Int, to: Int) {
        Collections.swap(list, from, to)
        notifyItemMoved(from, to)
    }

}

DiffCallback.kt

class DiffCallback(
    val oldList: List<Item>,
    var newList: List<Item>
) : DiffUtil.Callback() {

    override fun getOldListSize(): Int {
        return oldList.size
    }

    override fun getNewListSize(): Int {
        return newList.size
    }

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        val oldItem = oldList[oldItemPosition]
        val newItem = newList[newItemPosition]
        return oldItem.id == newItem.id
    }

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        val oldItem = oldList[oldItemPosition]
        val newItem = newList[newItemPosition]
        return compareContents(oldItem, newItem)
    }
}

Call itemMoved每个位置的变化:

override fun onMove(
    recyclerView: RecyclerView,
    viewHolder: RecyclerView.ViewHolder,
    target: RecyclerView.ViewHolder
): Boolean {
    val from = viewHolder.bindingAdapterPosition
    val to = target.bindingAdapterPosition
    itemListAdapter.itemMoved(from, to)

    // Update database as well if needed

    return true
}

当从 Room 数据库接收更新时:

您可能还想检查当前是否使用拖动选定更改时 https://developer.android.com/reference/androidx/recyclerview/widget/ItemTouchHelper.Callback#onSelectedChanged(androidx.recyclerview.widget.RecyclerView.ViewHolder,%20int)如果您还更新数据库,则每个位置都会发生变化,以防止不必要的调用submitList

list.observe(viewLifecycleOwner, { updatedList ->
    listAdapter.submitList(updatedList)
})
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 DiffUtil 在 RecyclerView 上添加拖放 的相关文章

  • 在 PushSharp 4.0 中构建 GCM 消息

    我对如何使用 PushSharp 构建 GCM 推送通知的消息正文感到有些困惑 GitHub 存储库中的文档和测试文件显示的消息结构如下 broker QueueNotification new GcmNotification Regist
  • LoaderManager 不接受“这个”

    好吧 我投降 我想不明白 我正在学习 Udacity 的 Android 基础知识课程 需要了解如何使用加载器加载数据 但是 当我使用以下行时 this 以红色突出显示并显示以下错误 Wrong 3rd argument type Foun
  • 如何获取拍摄照片的uri?

    我想实现什么目标 我想获取捕获图像的 URI 并将其保存在 Firebase 上 我尝试了什么 首先我需要打开相机 下面我是如何做到的 Intent cameraIntent new Intent android provider Medi
  • Android 7.0+ 屏幕关闭时前台服务无法接收位置更新

    我正在尝试创建一个 Android 应用程序 在设备屏幕关闭时连续实时记录设备位置数据 我的代码可以在 Android 6 0 及更早版本中正常运行 但 Android 7 0 似乎会破坏我的应用程序 我已经实现了一个 Android 前台
  • android OpenGl 如何绘制一个矩形

    我想用OpenGL画一个矩形 package jnidemo example com openglsquare import android content Context import android opengl GLSurfaceVi
  • 如何更改选项卡之间的 FloatingActionButton?

    我正在尝试实施浮动操作按钮 from 谷歌设计支持库进入三个选项卡中的两个 并根据材质设计指南 FloatingActionButton https www google com design spec components buttons
  • 活动侦听器 - Google 云消息传递 - BroadcastReceiver

    我已经在我的 Android 应用程序中实现了 GCM 并且它在接收消息方面工作正常 BroadcastReceiver 是根据 Google 提供的示例在清单文件中设置的 我的问题如下 如果用户打开应用程序并且我想更新该视图中的一些结果
  • 在使用单独方向布局旋转设备的同时继续播放 YouTube 播放器

    我正在尝试将包含 YouTube 播放器的视图添加到当我旋转设备时继续播放的活动 由于 UI 不仅仅包含视频 因此我使用YouTubePlayerFragment 当方向从纵向变为横向时 系统应使用不同的布局文件 此布局还包括 YouTub
  • 在手机上单步执行 Android 代码 - 大行号差异

    我正在尝试调试与 Samsung Captivate Galaxy S 上的 ListView 相关的一些代码 我在代码中的某个位置放置了断点 当它停止时 我会在堆栈上返回几帧到 ListView 源 现在 我可以预期会出现一些不匹配的情况
  • Android - 超链接不可点击

    我的应用程序中有一些链接 一个用于网站 一个用于电话号码 一个用于电子邮件 电子邮件和电话链接均有效且可点击 但由于某种原因 网站超链接仍然无法点击 有什么想法吗 代码如下
  • 删除 ios 和 android 的 PhoneGap 中的闪屏

    我正在尝试在 ios 和 android 的phonegap应用程序中完全删除启动屏幕 这navigator hide 函数仅在加载 html 页面后才起作用 但我需要在此之前删除启动屏幕 请告诉我是否有任何选项可以执行此操作 Cordov
  • 在android中构建照片上传应用程序[重复]

    这个问题在这里已经有答案了 可能的重复 从活动中调用相机 捕获图像并上传到服务器 https stackoverflow com questions 10679571 calling camera from an activity capt
  • C# Response.Write pdf 不适用于 Android 浏览器

    我目前在 Android 环境中使用 pdf 导出时遇到了巨大的问题 我正在使用报告查看器控件将报告呈现为字节数组 接下来我使用response binarywrite方法将字节流输出到浏览器 这适用于所有浏览器以及 iPhone 和 iP
  • 从自定义标记获取附近的地点

    我有一个标记列表 并且想使用我的标记列表获取附近的地点 我试过检查一下here https stackoverflow com questions 32284708 how to constantly detect nearby marke
  • 用于代码生成的 ANTLR 工具版本 4.5.3 与当前运行时版本 4.7.1 不匹配

    我在 DataBindingMapperImpl java 中遇到一个特定数据绑定的错误 这会在构建项目时导致以下错误 用于代码生成的 ANTLR 工具版本 4 5 3 与当前运行时版本 4 7 1 不匹配 用于解析器编译的 ANTLR 运
  • Gradle:找不到受信任的证书

    我正在尝试使用 Gradle 在 Ubuntu 服务器上构建我的 Android 项目 在我的 Windows 10 PC 上使用 Android Studio 构建工作正常 但使用 gradlew build or gradlew cle
  • 无法从新版 Google 相册应用中同时选择照片和视频

    Google 相册更新后 我无法同时选择视频和照片 如果我使用单个 视频 或 图像 意图 它会像平常一样工作 在视频 照片意图中 它忽略第二个参数 如果第一个是视频 它将是视频意图 如果它是照片 您将建议选择照片 Intent intent
  • Android:从http获取文件并存储在SDCard中

    我已经遵循了许多类似问题中所写的内容 但仍然存在问题 从jsp我得到一个pdf 如果我转到URL 浏览器会自动打开pdf jsp页面会执行类似以下操作 Gets the pdf from the database BufferedInput
  • Eclipse Android 插件中出现“调试证书已过期”错误

    我正在使用 Eclipse Android 插件来构建一个项目 但是我 在控制台窗口中出现此错误 2010 02 03 10 31 14 androidVNC Error generating final archive Debug cer
  • 如何在声音输入时触发振动?

    我正在尝试创建一个 Android 应用程序 在其中过滤蜂鸣声的一个特定频率并使手机振动 我正在从移动设备的 MIC 获取输入并使用 MediaRecorder 类 通过使用该类 我可以录制 保存和播放输入 现在我需要我的手机在发出蜂鸣声

随机推荐

  • 函数“[<-”将_替换_一个元素,但不会追加_元素_

    我在使用时注意到以下几点 lt 我成功于替换元素但不位于追加向量的一个元素 例子 VarX lt integer VarX 1 lt 11 lt VarX 2 22 VarX 1 11 Expected the value of VarX
  • 使用 jQuery 保留切换状态[重复]

    这个问题在这里已经有答案了 可能的重复 带 Cookie 的 jQuery 切换 https stackoverflow com questions 2523189 jquery toggle with cookie 我有一个简单的切换 但
  • Chrome 开发工具命中代码但未命中断点

    我在 chrome 开发工具上启用了断点 并且在一行上有一个断点 我知道 chrome 正在运行 因为我将断点放在具有以下语句的行上 alert why is this not breaking 如果我在本地主机中找到该文件 则断点有效 断
  • 用于(联合国)结构化文本文档的词法分析器/解析器[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有很多脚本解析器和词法分析器 即结构化计算机语言 但我正在寻找一个可以将 几乎 非结构化文本文档分成更
  • 唯一约束与唯一索引?

    之间有区别吗 CREATE TABLE p product no integer name text UNIQUE price numeric and CREATE TABLE p product no integer name text
  • 内联 PTX 汇编代码强大吗?

    我看到一些代码示例 人们在 C 代码中使用内联 PTX 汇编代码 CUDA工具包中的文档提到PTX很强大 为什么会这样呢 如果我们在 C 代码中使用这样的代码 我们会得到什么好处 内联 PTX 使您可以访问未通过 CUDA 内在函数公开的指
  • Grep 仅在“:”之前匹配

    你好 我怎样才能 grep 只匹配之前 mark 如果我跑grep test1 file 它显示所有三行 test1 x 29688 test1 test2 test2 x 22611 test1 test3 x 25163 test1 t
  • 从实体获取单列

    如何从查询中获取单个列而不是整个对象 我可以这样做来获取整个对象 但我想要的只是名称 IList
  • 为 html5 输入类型渲染 asp.TextBox =“date”

    不知道以前有没有问过 也没找到 是否可以控制由 asp TextBox 呈现的输入文本的类型 我想把它改成
  • 无需更改代码即可重新部署 Heroku 应用程序

    我想部署一个 Heroku 应用程序 最好使用git push u heroku master 然而 只有当有任何待处理的提交要推送到 master 时 这才有效 在没有任何内容可推送的情况下如何重新部署应用程序 我试过git push u
  • 我的 MS Access 数据库不会更新 asp.net

    我正在尝试更新我的数据库但没有成功 这就是我的桌子的样子 https i stack imgur com Q6EDk png https i stack imgur com Q6EDk png 打开模态后 它看起来像这样 https i s
  • /var/lib/docker/中docker目录结构的作用

    当我启动一个新的 docker 守护进程时 docker 目录如下 var lib docker aufs diff layers mnt containers graph init dockerinit 0 7 3 linkgraph d
  • 打印表数据mysql php

    我在尝试打印表格的一些数据时遇到问题 我是 php mysql 的新手 但我认为我的代码是正确的 这里是 h1 Lista de usu rios h1
  • 是否有一个包可以维护所有带有符号的货币列表?

    是否有一个 python 包提供所有 或相当完整 货币的列表与符号 如美元的 有优秀的pycountry 贪财的 https github com limist py moneyed and ccy http code google com
  • 如何在 Flutter Provider 中删除 StreamController 中的数据?

    我正在使用provider来构建我的应用程序 因此数据被添加到StreamController中 每次刷新我的应用程序时 它都会调用API 然后将数据推送到StreamController 问题是如何在替换之前删除数据新的那一个 contr
  • Nodemailer发送日历事件并将其添加到谷歌日历

    我正在尝试使用 nodemailer 将日历事件发送到 Gmail 帐户 这是我的代码 let transporter nodemailer createTransport host smtp gmail com port 587 secu
  • 如何在 MSSQL 中获取 CURRENT_DATE?

    我正在使用 jpa 3 o 和 Hibernate 我有一个命名查询 SELECT COUNT wt id FROM WPSTransaction wt WHERE wt createdDate gt CURRENT DATE WPSTra
  • 检查 Objective-C 块类型?

    这主要是出于好奇 我不太确定它的实际用途是什么 但就这样吧 由于块也是 Objective C 对象 是否可以检查它们的类型 也就是说 它是否响应isKindOfClass 消息以及如何使用该消息来处理块 我天真的以为事情大概是这样的 vo
  • 在 Web 浏览器中禁用 F5 [重复]

    这个问题在这里已经有答案了 可能的重复 禁用浏览器的后退按钮 https stackoverflow com questions 961188 disable browsers back button 如何禁用浏览器上的 F5 刷新 htt
  • 使用 DiffUtil 在 RecyclerView 上添加拖放

    我有一个从房间数据库更新的列表 我从 Room 收到更新的数据作为新列表 然后将其传递给列表适配器 https developer android com reference androidx recyclerview widget Lis