Android新的工具类DiffUt

本文由张旭童投稿。

张旭童的博客      概述DiffUtil是support-v7:4..0中的新工具类,它用来比较两个数据集,寻找出旧数据集-》新数据集的最小变化量。

说到数据集,相信大家知道它是和谁相关的了,就是我的最爱,RecyclerView。

就我使用的这几天来看,它最大的用处就是在RecyclerView刷新时,不再无脑mAdapter.notifyDataSetChanged()。

以前无脑mAdapter.notifyDataSetChanged()有两个缺点:

不会触发RecyclerView的动画(删除、新增、位移、change动画)

性能较低,毕竟是无脑的刷新了一遍整个RecyclerView,极端情况下:新老数据集一模一样,效率是最低的。

使用DiffUtil后,改为如下代码:

DiffUtil.DiffResultdiffResult=DiffUtil.calculateDiff(newDiffCallBack(mDatas,newDatas),true);diffResult.dispatchUpdatesTo(mAdapter);

它会自动计算新老数据集的差异,并根据差异情况,自动调用以下四个方法

adapter.notifyItemRangeInserted(position,count);adapter.notifyItemRangeRemoved(position,count);adapter.notifyItemMoved(fromPosition,toPosition);adapter.notifyItemRangeChanged(position,count,payload);

显然,这个四个方法在执行时都是伴有RecyclerView的动画的,且都是定向刷新方法,刷新效率蹭蹭的上升了。

老规矩,先上图,

图一是无脑mAdapter.notifyDataSetChanged()的效果图,可以看到刷新交互很生硬,Item突然的出现在某个位置:

图二是使用DiffUtils的效果图,最明显的是有插入、移动Item的动画:

转成GIF有些渣,下载文末Demo运行效果更佳哦。

本文将包含且不仅包含以下内容:

先介绍DiffUtil的简单用法,实现刷新时的“增量更新”效果。(“增量更新”是我自己的叫法)

DiffUtil的高级用法,在某项Item只有内容(data)变化,位置(position)未变化时,完成部分更新(官方称之为Partialbind,部分绑定)。

了解到RecyclerView.Adapter还有publicvoidonBindViewHolder(VHholder,intposition,ListObjectpayloads)方法,并掌握它。

4在子线程中计算DiffResult,在主线程中刷新RecyclerView。

5少部分人不喜欢的notifyItemChanged()导致Item白光一闪的动画如何去除。

6DiffUtil部分类、方法官方注释的汉化

      DiffUtil的简单用法前文也提到,DiffUtil是帮助我们在刷新RecyclerView时,计算新老数据集的差异,并自动调用RecyclerView.Adapter的刷新方法,以完成高效刷新并伴有Item动画的效果。

这里需要读者脑补一个简单的RecyclerView展示列表的代码,当然还有个按钮点击模拟刷新。

ok,脑补成功,继续...

下面开始进入正题,简单使用DiffUtil,我们需要且仅需要额外编写一个类。

想成为文艺青年,我们需要实现一个继承自DiffUtil.Callback的类,实现它的四个abstract方法。

虽然这个类叫Callback,但是把它理解成:定义了一些用来比较新老Item是否相等的契约(Contract)、规则(Rule)的类,更合适。

DiffUtil.Callback抽象类如下:

本Demo如下实现DiffUtil.Callback,核心方法配有中英双语注释(说人话就是,翻译了官方的英文注释,方便大家更好理解)。

注释张写了这么详细的注释+简单的代码,相信一眼可懂。然后在使用时,注释掉你以前写的notifyDatasetChanged()方法吧,替换成以下代码:

讲解:步骤一

在将newDatas设置给Adapter之前,先调用DiffUtil.calculateDiff()方法,计算出新老数据集转化的最小更新集,就是DiffUtil.DiffResult对象。DiffUtil.calculateDiff()方法定义如下:第一个参数是DiffUtil.Callback对象,第二个参数代表是否检测Item的移动,改为false算法效率更高,按需设置,我们这里是true。

publicstaticDiffResultcalculateDiff(Callbackcb,booleandetectMoves)

步骤二

然后利用DiffUtil.DiffResult对象的dispatchUpdatesTo()方法,传入RecyclerView的Adapter,替代普通青年才用的mAdapter.notifyDataSetChanged()方法。查看源码可知,该方法内部,就是根据情况调用了adapter的四大定向刷新方法。

小结:

所以说,DiffUtil不仅仅只能和RecyclerView配合,我们也可以自己实现ListUpdateCallback接口的四个方法去做一些事情。(我暂时不负责任随便一想,想到可以配合自己项目里的九宫格控件?或者优化我上篇文章写的NestFullListView?小安利,见ListView、RecyclerView、ScrollView里嵌套ListView相对优雅的解决方案:







































白癜风医院地址
北京哪里治疗白癜风便宜



转载请注明:http://www.gslnbdf.com/jbxx/2872.html