RecyclerView数据更新神器 - DiffUtil

概述

DiffUtil是support-v7:24.2.0新增的工具类,它主要是用来计算两个数据集之间的差异,计算出旧数据集->新数据集的最小变化量,并将其返回。

算法

DiffUtil内部采用ugene W. Myers’s difference 算法。该算法对空间做了优化,并使用O(N)空间来计算两个列表添加和删除的最小操作数,算法的时间复杂度为O(N + D ^ 2)。由于该算法不支持移动的Item,因而Google大牛在此基础上改进支持计算移动的Item。造成的后果就是,DiffUtil需要对结果进行第二遍运算,以便于计算移动的Item,从而更加耗费性能。此时,时间的复杂度为O(N ^ 2), 其中N是添加和删除操作的总数。对于根据约束条件排序的数据集,可以禁用移动Item的检测以提高性能。

用途

DiffUtil主要是与RecyclerView配合使用。其中,由DiffUtil找出每个Item的变化,由RecyclerView.Adapter更新UI。这样的好处就是,在数据集变化时,RecyclerView.Adapter不用无脑的调用notifyDataSetChanged()方法。

核心类

DiffUtil.Callback

DiffUtil.Callback是一个抽象类,在计算两个列表之间的差异时,由DiffUtil回调此类。在该类中,定义了5个抽象方法:

  • int getOldListSize(): 获取旧数据集的长度
  • int getNewListSize(): 获取新数据集的长度
  • boolean areItemsTheSame(int oldItemPosition, int newItemPosition):用来判断 两个对象是否是相同的Item
  • boolean areContentsTheSame(int oldItemPosition, int newItemPosition):用来检查 两个item是否含有相同的数据
  • Object getChangePayload(int oldItemPosition, int newItemPosition):后续再说

DiffUtil.DiffResult

DiffUtil.DiffResult用于保存DiffUtil计算出的数据集之间的差异信息,其可以将差异信息分配给RecyclerView.Adapter,以便更新UI。

核心方法

  • calculateDiff(DiffUtil.Callback cb)
  • calculateDiff(DiffUtil.Callback cb, boolean detectMoves)

这两个方法都是用来计算旧数据集->新数据集的最小变化量,并起将其返回。其中,第一个方法是第二个方法的特例,默认开启移动Item的检测:

public static DiffResult calculateDiff(Callback cb) {

    return calculateDiff(cb, true);

}

如果禁用移动Item的检测,可以调用第二个方法,并将detectMoves参数设置为false。

简单使用

前文,已经提到DiffUtil主要是与RecyclerView配合使用,以便高效的更新数据集。

  1. 创建Bean

    data class DiffBean(var name: String, var desc: String) {
    
        override fun equals(o: Any?): Boolean {
            if (this === o) return true
            if (o == null || javaClass != o.javaClass) return false
    
            val diff = o as DiffBean?
    
            return diff!!.name == name
        }
    
        override fun hashCode(): Int {
            var result = name?.hashCode() ?: 0
            return result
        }
    }
    
  2. 创建DiffUtil.Callback

    class Diff

你可能感兴趣的:(AndroidSurpport,android,DiffUtil,RecyclerView,数据更新)