RecyclerView数据更新神器 - DiffUtil

DiffUtil是Android中的一个工具类,用于计算两个数据集的差异,并提供高效的RecyclerView数据更新方案。它采用O(N)空间的ugene W. Myers’s difference算法,通过DiffUtil.Callback比较对象并返回变化信息。DiffUtil避免了无脑调用notifyDataSetChanged(),通过DiffResult更新UI,提升性能。使用时需自定义Callback,实现特定比较逻辑,并在Adapter中处理局部更新。
摘要由CSDN通过智能技术生成

概述

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
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值