Android DiffUtil

  Android 的recyclerview-v7:24.2.0 发布后多了个DiffUtil工具类,这个工具类能够大大解放了Android开发者的一个苦恼:RecyclerView局部刷新和重新刷新时实际只改变了部分数据。

  DiffUtil能够计算两个列表之间的差值,并计算出旧列表变换到新列表的过程(DiffResult),DiffResult可以直接应用到RecyclerView的Adapter中,DiffResult会使用Adapter的notifyItemRangeChanged等方法来更新RecyclerView。

  DiffUtil使用了Eugene W.Myers‘s difference algorithm 去计算从旧集合到新集合的最小更新序列,Myers 算法并没有处理集合中的子项偏移情况,所以如果选择了要计算偏移情况的话,需要进行第二次的运算来检查子项偏移,所以会产生更多的计算时间成本。当集合的数据量较大时,Myers算法的处理时间会较长,所以不要在集合数据量大时在主线程进行Diff运算,应该放在后台线程中进行运算,将运算结果(DiffResult)在主线程进行更新RecyclerView。需要值得注意的是,子项偏移的运算会比较明显得增加Diff时间,所以在集合默认是排序情况下,关闭该功能。

  DiffUtil的Demo可以在网络上其他地方找到,这里不再赘述,只简单提下大致使用方法。

1、calculateDiff是最核心的方法,Callback并不是我们常见的回调,更准确点说应该是一个策略

DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(DiffUtil.Callback, boolean);

2、DiffUtil.Callback可实现的方法,DiffUtil会对每个position调用对应的方法,我们只需要在Callback中告诉DiffUtil,在哪个位置中,如何判别两个列表在这个位置是否是同一个子项,如果是,有没有局部变化,如果有局部变化,都变了哪里?DiffUtil只需要知道这些,就可以计算出DiffResult

/**
     * A Callback class used by DiffUtil while calculating the diff between two lists.
     */
    public abstract static class Callback {
        /**
         * Returns the size of the old list.
         *
         * @return The size of the old list.
         */
        public abstract int getOldListSize();

        /**
         * Returns the size of the new list.
         *
         * @return The size of the new list.
         */
        public abstract int getNewListSize();

        /**
         * Called by the DiffUtil to decide whether two object represent the same Item.
         * <p>
         * For example, if your items have unique ids, this method should check their id equality.
         *
         * @param oldItemPosition The position of the item in the old list
         * @param newItemPosition The position of the item in the new list
         * @return True if the two items represent the same object or false if they are different.
         */
        public abstract boolean areItemsTheSame(int oldItemPosition, int newItemPosition);

        /**
         * Called by the DiffUtil when it wants to check whether two items have the same data.
         * DiffUtil uses this information to detect if the contents of an item has changed.
         * <p>
         * DiffUtil uses this method to check equality instead of {@link Object#equals(Object)}
         * so that you can change its behavior depending on your UI.
         * For example, if you are using DiffUtil with a
         * {@link android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}, you should
         * return whether the items‘ visual representations are the same.
         * <p>
         * This method is called only if {@link #areItemsTheSame(int, int)} returns
         * {@code true} for these items.
         *
         * @param oldItemPosition The position of the item in the old list
         * @param newItemPosition The position of the item in the new list which replaces the
         *                        oldItem
         * @return True if the contents of the items are the same or false if they are different.
         */
        public abstract boolean areContentsTheSame(int oldItemPosition, int newItemPosition);

        /**
         * When {@link #areItemsTheSame(int, int)} returns {@code true} for two items and
         * {@link #areContentsTheSame(int, int)} returns false for them, DiffUtil
         * calls this method to get a payload about the change.
         * <p>
         * For example, if you are using DiffUtil with {@link RecyclerView}, you can return the
         * particular field that changed in the item and your
         * {@link android.support.v7.widget.RecyclerView.ItemAnimator ItemAnimator} can use that
         * information to run the correct animation.
         * <p>
         * Default implementation returns {@code null}.
         *
         * @param oldItemPosition The position of the item in the old list
         * @param newItemPosition The position of the item in the new list
         *
         * @return A payload object that represents the change between the two items.
         */
        @Nullable
        public Object getChangePayload(int oldItemPosition, int newItemPosition) {
            return null;
        }
    }

 3、DiffResult应用到RecyclerView的Adapter.

 DiffResult.dispatchUpdatesTo(RecyclerView.Adapter);

 4、关于Adapter以前的一个知识点,payloads,可能有些朋友还不知道Adapter还有一个onBindViewHolder重载方法,比常见的onBindViewHolder多一个参数:List<Object> payloads。当DiffResult中有某一项出现两个列表实际上在该位置是同一个子项,但是发生了局部变化,则调用该重载方法时带上payloads,payloads中的对象可以在Callback的getChangePayload给定。payloads不会为null,所以检查payloads是否为空,为空,直接调用默认的onBindViewHolder即可。

public void onBindViewHolder(StudentViewHolder holder, int position, List<Object> payloads) {}

  

  

时间: 2024-10-15 02:10:24

Android DiffUtil的相关文章

【Android】详解7.0带来的新工具类:DiffUtil

一 概述 DiffUtil是support-v7:24.2.0中的新工具类,它用来比较两个数据集,寻找出旧数据集->新数据集的最小变化量. 说到数据集,相信大家知道它是和谁相关的了,就是我的最爱,RecyclerView. 就我使用的这几天来看,它最大的用处就是在RecyclerView刷新时,不再无脑mAdapter.notifyDataSetChanged(). 以前无脑mAdapter.notifyDataSetChanged()有两个缺点: 不会触发RecyclerView的动画(删除.

Android的Kotlin秘方(II):RecyclerView 和 DiffUtil

作者:Antonio Leiva 时间:Sep 12, 2016 原文链接:http://antonioleiva.com/recyclerview-diffutil-kotlin/ 如你所知,在[支持库24(the Support Library 24)]中包括一个新的.适用.方便的类:DiffUtil,这使你摆脱对单元改变和更新它们的无聊和易出错. 如果你还不了解它,可以阅读Nicola Despotoski的这篇好文章了解它.这篇文章解释怎样容易处理它. 实际上,Java语言引入许多模板,

Android开发学习之路-DiffUtil使用教程

谷歌最近更新了Support Library 24.2.0,而DiffUtil就是在这个版本添加的一个工具类. DiffUtil是一个查找集合变化的工具类,是搭配RecyclerView一起使用的,如果你还不了解RecyclerView,可以阅读一些资料或者我的博客:RecyclerView使用初探 根据惯例,先放效果图: 可以看到,当我们点击按钮的时候,这个RecyclerView所显示的集合发生了改变,有的元素被增加了(8.Jason),也有的元素被移动了(3.Rose),甚至是被修改了(2

在 2016 年学 Android 是一种什么样的体验?

@author ASCE1885的 Github 简书 微博 CSDN 知乎 本文由于潜在的商业目的,不开放全文转载许可,谢谢! 广而告之时间:我的新书<Android 高级进阶>(https://item.jd.com/10821975932.html )在京东开始预售了,欢迎订购! 转眼间 2016 年的电量已不足 20%,不禁感慨 How Time Flies!不知不觉 Android 移动开发已经走过了八年的光阴,在这八年的时间中,Android 开发从最初的简单调用系统 API,到各

【Android】你可能不知道的Support(一) 0步自动定向刷新:SortedList

转载请标明出处: http://blog.csdn.net/zxt0601/article/details/53495709 本文出自:[张旭童的博客](http://blog.csdn.net/zxt0601) 代码传送门:喜欢的话,随手点个star.多谢 https://github.com/mcxtzhang/SupportDemos 背景: 打算写一个系列了,讲解Android Support包内那些常用or冷门有用的工具类的合集. 最近leader在优化IM会话列表,同事以前的做法是无

Android开发Diffutils打造不一样的recyclerview

简述 DiffUtil是recyclerview support library v7 24.2.0版本中新增的类,根据Google官方文档的介绍,DiffUtil的作用是比较两个数据列表并能计算出一系列将旧数据表转换成新数据表的操作.这个概念比较抽象,换一种方式理解,DiffUtil是一个工具类,当你的RecyclerView需要更新数据时,将新旧数据集传给它,它就能快速告知adapter有哪些数据需要更新.就相当于如果改变了就对某个item刷新,没改变就没刷新,可以简称为局部刷新. 无脑刷新

[Android Pro] AndroidX重构和映射

原文地址:https://developer.android.com/topic/libraries/support-library/refactor https://blog.csdn.net/chen_xi_hao/article/details/81741486 AndroidX重构 未与Android操作系统捆绑在一起的API包将被重构到新的androidx命名空间中.只有包名和Maven工件名受到影响; 原来的类名,方法名和字段名不会更改.有关AndroidX重构的更多信息,请参阅博客

Android App 卡顿分析

极力推荐Android 开发大总结文章:欢迎收藏 程序员Android 力荐 ,Android 开发者需要的必备技能 Android App 反应卡顿,从技术上将就是UI 渲染慢. UI渲染是从您的应用程序生成一个框架并将其显示在屏幕上的行为. 为了确保用户与您的应用程序的交互顺利,您的应用程序应该在16ms内渲染帧数达到每秒60帧(为什么60fps?). 如果您的应用程序因UI渲染速度缓慢而受到影响,那么系统将被迫跳过帧,用户将感觉到您的应用程序中出现卡顿. 我们把这个叫做jank. 本篇文章

android开发之onCreate( )方法详解

onCreate( )方法是android应用程序中最常见的方法之一,那么,我们在使用onCreate()方法的时候应该注意哪些问题呢? 先看看Google Android Developers官网上的解释: onCreate(Bundle) is where you initialize your activity. Most importantly, here you will usually call setContentView(int) with a layout resource d