原文:Android RecyclerView使用ListAdapter高效刷新数据 - Stars-One的杂货小窝

我们都知道,当RecyclerView数据源更新后,还需要通过adapter调用对应的方法,从而让RecyclerView重新绘制页面

本次也是介绍了用另外一种方法来实现RecyclerView高效刷新数据的功能

问题

首先,默认各位是有使用RecyclerView的经验的,

对于数据的更新,我们一般可以使用adapter的下面四个方法:

  • notifyDataSetChanged() 整个数据改变
  • notifyItemInserted() 往某个下标插入数据,并触发动画
  • notifyItemChanged() 更新某个下标的数据,并触发动画
  • notifyItemRangeRemoved() 移除某个下标的数据,并触发动画

但是,其中下面的三个方法传参需要给个position下标,这个有时候每次由我们去计算获取,很麻烦,而且我们还要处理对应的增删改的逻辑

所以之后Android官方也是出了一个新的工具DiffUtils

DiffUtils使用

DiffUtil主要提供了一个静态方法供我们调用calculateDiff(),其中的参数为一个Callback静态抽象类,我们需要先写一个类,继承并实现其中的方法

class DiffCallBack(val oldList: ArrayList<Person>, val newList: ArrayList<Person>) :DiffUtil.Callback() {

    //判断两个对象是否相同
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { return oldList[oldItemPosition].id == newList[newItemPosition].id
} override fun getOldListSize(): Int {
return oldList.size
} override fun getNewListSize(): Int {
return newList.size
} //判断两个对象内容是否相同
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val newItem = newList[newItemPosition]
val oldItem = oldList[oldItemPosition] //如果新数据和旧数据的名称和年龄相同,则视为两个item的内容相同
return oldItem.age == newItem.age && oldItem.name == newItem.name
} }

实际上,此类就是用来比较两个List的不同之处,定义区分两个同类的对象,是否相同,从上面的两个方法也是能够看得出来

首先,areItemsTheSame()方法先判断两个item是否为同个对象

这里我是选用了id作为唯一标识来区分是否为同一对象,当然,也可以用内存地址来比对,如果是内存地址来比对,则涉及浅拷贝和深拷贝的问题,这里不扩展讲解了

其次,再通过areContentsTheSame()方法来判断两个item内容是否相同

现在,我们有了一个Callback类,可以使用calculateDiff()方法了:

val oldList = adapter.getData()
//深拷贝oldList得到newList,然后对newList按照业务进行增删改的操作,这里代码就省略了.. //计算不同之处
val diffResult = DiffUtil.calculateDiff(DiffCallBack(oldList,newList))
//adapter设置新数据
adapter.setData(newList)
//将变更操作分发给adapter
diffResult.dispatchUpdatesTo(adapter)

上面给的代码可能不是太全,因为这种方法不是我们推荐的写法,更推荐使用ListAdapter来实现此功能,具体可看下文

实际上,DiffUtil算法还是耗时间的,如果数据更多,估计时间也会随之增多,所以,官方推荐开启个异步线程来处理计算,之后分发操作再切换UI线程进行数据的更新操作

ListAdapter使用

ListAdapter其实就是对上面的DiffUtil的一个封装类,以往,我们的Adapter都是继承了RecyclerView.Adapter,并在其中写了个List去装载数据,十分麻烦

ListAdapter里面维护着线程池并且还会为我们将视图修改操作移到主线程,这样我们就可以很方便的使用DiffUtil了

如果我们将此Adapter替换成继承与ListAdapter,那么都不需要我们在类中写上个List,代码示例如下:

class RvAdapter() : ListAdapter<Person, RvAdapter.ViewHolder>(diffCallback) {

    companion object {
val diffCallback = object : DiffUtil.ItemCallback<Person>() {
override fun areItemsTheSame(oldItem: Person, newItem: Person): Boolean {
return oldItem.id == newItem.id
} override fun areContentsTheSame(oldItem: Person, newItem: Person): Boolean {
//如果新数据和旧数据的名称和年龄相同,则视为两个item的内容相同
return oldItem.age == newItem.age && oldItem.name == newItem.name
} }
} class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var tvAge: TextView = itemView.findViewById(R.id.tvAge)
var tvName: TextView = itemView.findViewById(R.id.tvUserName)
} override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val itemView = View.inflate(parent.context, R.layout.rv_item_person, null)
return ViewHolder(itemView)
} override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = getItem(position)
holder.tvName.text = item.name
holder.tvAge.text = item.age.toString()
}
}

ListAdapter<T,ViewHolder>第一个泛型即为你的数据实体类,第二个参数为ViewHolder类

注意: 之后的数据增删改查都需要调用adapter提供的submitList()方法即可

val oldList = adapter.currentList

val newList = oldList.map { it }.toMutableList()
newList.removeAt(10)
//下标2加个新数据
newList.add(2, Person(90, "我的", 72))
adapter.submitList(list)

效果:

参考

Android RecyclerView使用ListAdapter高效刷新数据的更多相关文章

  1. Android 5.X新特性之为RecyclerView添加下拉刷新和上拉加载及SwipeRefreshLayout实现原理

    RecyclerView已经写过两篇文章了,分别是Android 5.X新特性之RecyclerView基本解析及无限复用 和 Android 5.X新特性之为RecyclerView添加Header ...

  2. Android实现RecyclerView的下拉刷新和上拉载入很多其它

    需求 先上效果图, Material Design风格的下拉刷新和上拉载入很多其它. 源代码地址(欢迎star) https://github.com/studychen/SeeNewsV2 假设对于 ...

  3. Android回到页面并刷新数据

    通过对Android Activity的生命周期的了解,需要在后退页面重写onResume()的方法. 建立自己更新数据的函数,并在onCreate()方法中调用. @Override protect ...

  4. Android Viewpager PagerAdapter update data 刷新界面数据

    最近做的项目涉及到ViewPager数据刷新,网上的资料挺多,但是和现在做的这个不太相同,所以并没有找到有效的. 折腾了大半天,整理一下思路: 问题1: 后台刷新数据次数过多后,界面出现卡顿现象,判断 ...

  5. Android RecyclerView与ListView比较

    RecyclerView 概述 RecyclerView 集成自 ViewGroup .RecyclerView是Android-support-V7版本中新增的一个Widgets,官方对于它的介绍是 ...

  6. SwipeRefreshLayout + RecyclerView 实现 上拉刷新 和 下拉刷新

    下拉刷新和上拉刷新都用SwipeRefreshLayout 自带的进度条 布局 <?xml version="1.0" encoding="utf-8"? ...

  7. Android RecyclerView的基本使用

    Android RecyclerView 在去年的Google I/O大会上就推出来了,以前经常使用的ListView 继承的是AbsListView,而RecyclerView则直接继承 ViewG ...

  8. Android RecyclerView网格布局

    一个简单的网格布局activity_main.xml <?xml version="1.0" encoding="utf-8"?> <andr ...

  9. Android之SwipeRefreshLayout下拉刷新组件

    SwipeRefreshLayout概述 SwipeRefrshLayout是Google官方更新的一个Widget,可以实现下拉刷新的效果.该控件集成自ViewGroup在support-v4兼容包 ...

随机推荐

  1. BMP位图之8位位图(三)

    起始结构 typedef struct tagBITMAPFILEHEADER { WORD bfType; //类型名,字符串"BM", DWORD bfSize; //文件大小 ...

  2. Python-基础学习-第二轮

    目录 数据类型 文件 自调用其他程序 os.system函数 os.startfile 函数 subprocess 模块 线程和进程 创建新线程 共享数据的访问控制 deamon线程 多线程 JSON ...

  3. flutter系列之:widgets,构成flutter的基石

    目录 简介 StatelessWidget和StatefulWidget StatelessWidget详解 StatefulWidget详解 总结 简介 flutter中所有的组件都是由widget ...

  4. 延时任务-基于netty时间轮算法实现

    一.时间轮算法简介 为了大家能够理解下文中的代码,我们先来简单了解一下netty时间轮算法的核心原理 时间轮算法名副其实,时间轮就是一个环形的数据结构,类似于表盘,将时间轮分成多个bucket(比如: ...

  5. HCIA-Datacom 3.3 实验三:以太网链路聚合实验

    实验介绍 随着网络规模不断扩大,用户对骨干链路的带宽和可靠性提出越来越高的要求.在传统技术中,常用更换高速率的接口板或更换支持高速率接口板的设备的方式来增加带宽,但这种方案需要付出高额的费用,而且不够 ...

  6. Vue3 Transition 过渡效果之切换路由组件

    复习作用域插槽 组件可以被插入些许节点作为其子节点,插槽<slot>就是一个接口(或桥梁)引导这些节点进入组件.这些节点应该被渲染到组件里的具体哪个位置,就是具名插槽的作用.就像是给手机冲 ...

  7. Lua环境搭建编译[Lua5.2+VS2010]

    这里是我编译的和一个测试Demo:http://download.csdn.net/detail/allh45601/6783653 大家如果看我下边说的不是很清楚,可以下载这个具体工程: 群:103 ...

  8. redis-string类型命令

    一.APPEND key value 如果 key 已经存在,并且值为字符串,那么这个命令会把 value 追加到原来值(value)的结尾. 如果 key 不存在,那么它将首先创建一个空字符串的ke ...

  9. vscode 快速注释和撤回快捷键

    好家伙,天天忘,建议先练个十遍上手 1.快捷行注释 Ctrl + / 2.快捷块注释 Alt + Shift + A 3.撤回 Ctrl + Z 4.恢复撤回(撤回你的撤回) Ctrl + Shift ...

  10. Java 在Word文档中添加艺术字

    艺术字是以普通文字为基础,经过专业的字体设计师艺术加工的变形字体.字体特点符合文字含义.具有美观有趣.易认易识.醒目张扬等特性,是一种有图案意味或装饰意味的字体变形,常用来创建旗帜鲜明的标志或标题. ...