谷歌最近更新了Support Library 24.2.0,而DiffUtil就是在这个版本添加的一个工具类。
DiffUtil是一个查找集合变化的工具类,是搭配RecyclerView一起使用的,如果你还不了解RecyclerView,可以阅读一些资料或者我的博客:RecyclerView使用初探
根据惯例,先放效果图:
可以看到,当我们点击按钮的时候,这个RecyclerView所显示的集合发生了改变,有的元素被增加了(8.Jason),也有的元素被移动了(3.Rose),甚至是被修改了(2.Fndroid)。RecyclerView对于每个Item的动画是以不同方式刷新的:
- notifyItemInserted
- notifyItemChanged
- notifyItemMoved
- notifyItemRemoved
而对于连续的几个Item的刷新,可以调用:
- notifyItemRangeChanged
- notifyItemRangeInserted
- notifyItemRangeRemoved
而由于集合发生变化的时候,只可以调用notifyDataSetChanged方法进行整个界面的刷新,并不能根据集合的变化为每一个变化的元素添加动画。所以这里就有了DiffUtil来解决这个问题。
DiffUtil的作用,就是找出集合中每一个Item发生的变化,然后对每个变化给予对应的刷新。
这个DiffUtil使用的是Eugene Myers的差别算法,这个算法本身不能检查到元素的移动,也就是移动只能被算作先删除、再增加,而DiffUtil是在算法的结果后再进行一次移动检查。假设在不检测元素移动的情况下,算法的时间复杂度为O(N + D2),而检测元素移动则复杂度为O(N2)。所以,如果集合本身就已经排好序,可以不进行移动的检测提升效率。
下面我们一起来看看这个工具怎么用。
首先对于每个Item,数据是一个Student对象:
1 class Student {
2 private String name;
3 private int num;
4
5 public Student(String name, int num) {
6 this.name = name;
7 this.num = num;
8 }
9
10 public String getName() {
11 return name;
12 }
13
14 public void setName(String name) {
15 this.name = name;
16 }
17
18 public int getNum() {
19 return num;
20 }
21
22 public void setNum(int num) {
23 this.num = num;
24 }
25 }
接着我们定义布局(省略)和适配器:
1 class MyAdapter extends RecyclerView.Adapter {
2 private ArrayList<Student> data;
3
4 ArrayList<Student> getData() {
5 return data;
6 }
7
8 void setData(ArrayList<Student> data) {
9 this.data = new ArrayList<>(data);
10 }
11
12 @Override
13 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
14 View itemView = LayoutInflater.from(RecyclerViewActivity.this).inflate(R.layout.itemview, null);
15 return new MyViewHolder(itemView);
16 }
17
18 @Override
19 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
20 MyViewHolder myViewHolder = (MyViewHolder) holder;
21 Student student = data.get(position);
22 myViewHolder.tv.setText(student.getNum() + "." + student.getName());
23 }
24
25 @Override
26 public int getItemCount() {
27 return data.size();
28 }
29
30 class MyViewHolder extends RecyclerView.ViewHolder {
31 TextView tv;
32
33 MyViewHolder(View itemView) {
34 super(itemView);
35 tv = (TextView) itemView.findViewById(R.id.item_tv);
36 }
37 }
38 }
初始化数据集合:
1 private void initData() {
2 students = new ArrayList<>();
3 Student s1 = new Student("John", 1);
4 Student s2 = new Student("Curry", 2);
5 Student s3 = new Student("Rose", 3);
6 Student s4 = new Student("Dante", 4);
7 Student s5 = new Student("Lunar", 5);
8 students.add(s1);
9 students.add(s2);
10 students.add(s3);
11 students.add(s4);
12 students.add(s5);
13 }
接着实例化Adapter并设置给RecyclerView:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_view);
initData();
recyclerView = (RecyclerView) findViewById(R.id.rv);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new MyAdapter();
adapter.setData(students);
recyclerView.setAdapter(adapter);
}
这些内容