设为首页 加入收藏

TOP

Android开发学习之路-DiffUtil使用教程(二)
2017-10-13 10:35:48 】 浏览:6866
Tags:Android 开发 习之 -DiffUtil 使用 教程
都不是本篇的内容,但是,需要注意到的一个地方是Adapter的定义:

 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         // 省略部分代码
13          ......  
14     }   

这里的setData方法并不是直接将ArrayList的引用保存,而是重新的建立一个ArrayList,先记着,后面会解释为什么要这样做


DiffUtil的使用方法:

当鼠标按下时,修改ArrayList的内容:

 1     public void change(View view) {
 2         students.set(1, new Student("Fndroid", 2));
 3         students.add(new Student("Jason", 8));
 4         Student s2 = students.get(2);
 5         students.remove(2);
 6         students.add(s2);
 7 
 8         ArrayList<Student> old_students = adapter.getData();
 9         DiffUtil.DiffResult result = DiffUtil.calculateDiff(new MyCallback(old_students, students), true);
10         adapter.setData(students);
11         result.dispatchUpdatesTo(adapter);
12     }

2-6行是对集合进行修改,第8行先获取到adapter中的集合为旧的数据。

重点看第9行调用DiffUtil.calculateDiff方法来计算集合的差别,这里要传入一个CallBack接口的实现类(用于指定计算的规则)并且把新旧数据都传递给这个接口的实现类,最后还有一个boolean类型的参数,这个参数指定是否需要进行Move的检测,如果不需要,如果有Item移动了,会被认为是先remove,然后insert。这里指定为true,所以就有了动图显示的移动效果。

第10行重新将新的数据设置给Adapter。

第11行调用第9行得到的DiffResult对象的dispatchUpdatesTo方法通知RecyclerView刷新对应发生变化的Item。

这里回到上面说的setData方法,因为我们在这里要区分两个集合,如果在setData方法中直接保存引用,那么在2-6行的修改就直接修改了Adapter中的集合了(Java知识)。

如果设置不检查Item的移动,效果如下:

 

接着我们看看CallBack接口的实现类如何定义:

 1     private class MyCallback extends DiffUtil.Callback {
 2         private ArrayList<Student> old_students, new_students;
 3 
 4         MyCallback(ArrayList<Student> data, ArrayList<Student> students) {
 5             this.old_students = data;
 6             this.new_students = students;
 7         }
 8 
 9         @Override
10         public int getOldListSize() {
11             return old_students.size();
12         }
13 
14         @Override
15         public int getNewListSize() {
16             return new_students.size();
17         }
18 
19         // 判断Item是否已经存在
20         @Override
21         public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
22             return old_students.get(oldItemPosition).getNum() == new_students.get(newItemPosition).getNum();
23         }
24 
25         // 如果Item已经存在则会调用此方法,判断Item的内容是否一致
26         @Override
27         public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
28             return old_students.get(oldItemPosition).getName().equals(new_students.get(newItemPosition).getName());
29         }
30     }

这里根据学号判断是否同一个Item,根据姓名判断这个Item是否有被修改。

 

实际上,这个Callback抽象类还有一个方法getChangePayload(),这个方法的作用是我们可以通过这个方法告诉Adapter对这个Item进行局部的更新而不是整个更新。

先要知道这个payload是什么?payload是一个用来描述Item变化的对象,也就是我们的Item发生了哪些变化,这些变化就封装成一个payload,所以我们一般可以用Bundle来充当。

接着,getChangePayload()方法是在areItemsTheSame()返回true,而areContentsTheSame()返回false时被回调的,也就是一个Item的内容发生了变化,而这个变化有可能是局部的(例如微博的点赞,我们只需要刷新图标而不是整个Item)。所以可以在getChangePayload()中封装一个Object来告诉RecyclerView进行局部的刷新。

假设上例中学号和姓名用不同的TextView显示,当我们修改了一个学号对应的姓名时,局部刷新姓名即可(这里例子可能显得比较多余,但是如果一个Item很复杂,用处就比较大了):

先是重写Callback中的该方法:

1         @Nullable
2         @Override
3         public Object getChangePayload(int oldItemPosition, int newItemPosition) {
4             Student newStudent = newStudents.get(newItemPosition);
5             Bundle diffBundle = new Bundle();
6             diffBundle.putString(NAME_KEY, newStudent.getName());
7             return diffBundle;
8

返回的这

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Android快乐贪吃蛇游戏实战项目开.. 下一篇浅析Dagger2的使用

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目