Android使用DiffUtil智能地更新RecyclerView

DiffUtil是一个工具类,它会找出两个列表的差异,输出一个更新列表,并且可以用来通知RecyclerView的Adapter更新。

使用

DiffUtil会使用DiffUtil.Callback来计算两个列表的差异,其中DiffUtil.Callback是一个抽象类,需要我们实现它,它包含了四个抽象方法和一个非抽象方法:

  • getOldListSize():获取旧列表的大小
  • getNewListSize():获取新列表的大小
  • areItemsTheSame(int oldItemPosition, int newItemPosition):判断新旧列表两个位置的项目是否相同
  • areContentsTheSame(int oldItemPosition, int newItemPosition):判断新旧列表两个位置的项目数据是否相同,DiffUtil只会在areItemsTheSame()返回true时才调用此方法。
  • getChangePayload(int oldItemPosition, int newItemPosition):如果areItemTheSame()返回true,而areContentsTheSame()返回false,则DiffUtil会调用此方法来获取更改后的负载

示例

模型类:Employee

public class Employee {
    public int id;
    public String name;
    public String role;
}

实现DiffUtil.Callback

public class EmployeeDiffCallback extends DiffUtil.Callback {

    private final List<Employee> mOldEmployeeList;
    private final List<Employee> mNewEmployeeList;

    public EmployeeDiffCallback(List<Employee> oldEmployeeList, List<Employee> newEmployeeList) {
        this.mOldEmployeeList = oldEmployeeList;
        this.mNewEmployeeList = newEmployeeList;
    }

    @Override
    public int getOldListSize() {
        return mOldEmployeeList.size();
    }

    @Override
    public int getNewListSize() {
        return mNewEmployeeList.size();
    }

    @Override
    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        return mOldEmployeeList.get(oldItemPosition).getId() == mNewEmployeeList.get(
                newItemPosition).getId();
    }

    @Override
    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        final Employee oldEmployee = mOldEmployeeList.get(oldItemPosition);
        final Employee newEmployee = mNewEmployeeList.get(newItemPosition);

        return oldEmployee.getName().equals(newEmployee.getName());
    }

    @Nullable
    @Override
    public Object getChangePayload(int oldItemPosition, int newItemPosition) {
        // 如果要使用ItemAnimator,可以在实现此方法
        return super.getChangePayload(oldItemPosition, newItemPosition);
    }
}

在RecyclerViewAdapter处理列表数据的更新

public class CustomRecyclerViewAdapter extends RecyclerView.Adapter<CustomRecyclerViewAdapter.ViewHolder> {

  ...
       public void updateEmployeeListItems(List<Employee> employees) {
        final EmployeeDiffCallback diffCallback = new EmployeeDiffCallback(this.mEmployees, employees);
        final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);

        this.mEmployees.clear();
        this.mEmployees.addAll(employees);
        diffResult.dispatchUpdatesTo(this); //分发更新到RecyclerView Adapter
    }
}

DiffResult为计算差异后返回的结果,获取差异结果后,调用dispatchUpdatesTo(RecyclerView.Adapter)来分发更新的列表。 

DiffUtil调用了RecyclerView.Adapter的以下方法来通知Adapter来更新数据集:

  • notifyItemMoved()
  • notifyItemRangeChanged()
  • notifyItemRangeInserted()
  • notifyItemRangeRemoved()

版权声明:著作权归作者所有。

相关推荐

使用RecyclerView和LayoutAnimation给列表添加进入动画

这里讲解下使用RecyclerView和LayoutAnimation给列表添加进入动画。分为三个步骤:给列表项添加动画使用列表项的动画定义LayoutAnimationRecyclerView应用LayoutAnimation的动画使用LayoutAnimation定义动画的好处是,它是单独定义,可以应用于任何ViewGroup的子类。这里是以RecyclerView为示例。示例效果示例是一个向

webstorm激活License Server更新(2018-04-23)

webstorm激活步骤Activate new license with: 选择License ServerLicense Server填写激活服务器地址。持续更新webstorm激活服务器记录下网上搜索到的激活服务器地址。2018-04-23http://hb5.s.osidea.cc:10172018-01-18http://ide

CentOS 7更新为阿里云yum源

进入yum源的目录centos 7yum源目录为/etc/yum.repos.d$cd /etc/yum.repos.d 备份yum源在更新centos 7的yum源前先备份。$ sudo cp CentOS-Base.repo backup/ 如果没有bakcup目录先创建。下载阿里云yum源阿里云yum源列表:http://

Sql Server使用查询语句更新数据

Sql Server支持在一个sql语句里使用查询的数据更新表。简单更新简单的使用一个表的数据更新另一个表。UPDATE    table_a  SET    table_a.col1=table_b.col1 FROM    table_b  WHERE table_

使用ANDROID_ID唯一标识Android设备

使用Settings.Secure#ANDROID_ID 会返回每个用户唯一的64位hex字符串,它是在设备首次boot时生成。我们可以使用它来唯一标识Android设备。import android.provider.Settings.Secure; private String android_id = Secure.getString(ge