原文: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. Floyd算法详解

    Floyd本质上使用了DP思想,我们定义\(d[k][x][y]\)为允许经过前k个节点时,节点x与节点y之间的最短路径长度,显然初始值应该为\(d[k][x][y] = +\infin (k, x, ...

  2. Java集合容器的深度理解

    Java容器里有很多写好的容器API,这使我们很方便的可以存储.操作我们的数据. 下面是我写的容器的特点,一些容器的不同之处,从底层源码解析一下容器实现原理 一.常用的容器目录 上图可以看出,java ...

  3. flutter系列之:flutter架构什么的,看完这篇文章就全懂了

    目录 简介 Flutter的架构图 embedder engine Flutter framework Widgets Widgets的可扩展性 Widgets的状态管理 渲染和布局 总结 简介 Fl ...

  4. 如何在Linux快速搭建一套ADB环境

    一.ADB简介 1.什么是ADB Android Debug Bridge,安卓调试桥,它借助adb.exe(Android SDK安装目录platform-tools下),用于电脑端与模拟器或者真实 ...

  5. 使用二手 gopro 做行车记录仪

    背景 自打开了博客以后,一直在写技术说明文,今天打算写点程序以外的东西换换味口.前段时间在某鱼上以 300 元的价格入手了一套完整的 gopro3+ 运动摄像头,带一张 32G SD 卡,两块备用电池 ...

  6. 计算机的主存储器(RAM)

    主存储器是存放指令和数据的,并能由 CPU 直接随机存取的存储器.主要由存储体.控制线路.地址寄存器.数据寄存器和地址译码电路五部分组成.

  7. Linux安装JDK并配置环境变量

    Linux - 安装jdk并配置环境变量 1. 前往JDK官网, 地址:https://www.oracle.com/java/technologies/downloads/   复制下载链接 2.  ...

  8. 读取图片文件MetaFile放入Windows剪切板

    前言 前段时间群里有个小伙在工作中遇到一个问题,透明的图片存入剪切板在粘贴到adobe PDF中出现不透明问题但是粘贴到Excel可以,还有就是从excel复制再粘贴到PDF也是可以.小伙在群里发了两 ...

  9. 【manim】学习路径2-构建一些基础的图形,场景

    头文件引入 导入manim命名空间 from manim import * manim基本结构 这是一个最基本的manim结构,格式: from manim import * class 类的名字(S ...

  10. 前端利器躬行记(8)——VSCode插件研发

    VSCode提供了丰富的 API,可以借助编辑器扩展许多定制功能. 本次研发了一款名为 Search Method 的插件,在此记录整个研发过程. 一.准备工作 1)安装环境 首先是全局安装 yo 和 ...