【Android TimeCat】 RecyclerView的卡顿问题

背景

Time Cat中大量使用了RecycleView和折叠结构,虽然便于用户交互,但同时也使性能成为一个问题。

RecyclerView为什么会卡

RecyclerView作为v7包的新控件,自从推出就广受Android Developer们欢迎,实际上它已经取代了ListView和GridView两位老前辈的地位。然而不少亲们想必也已经发现了:没有优化过的Recycler性能很poor。上一篇博主使用的item也仅仅是一个图两串字而已,结果一滑动就卡的要命,不能忍!
那么why?回想在用ListViewGridViewadapter时,我们是用一种叫ViewHolder的自定义类(容器)来实现优化的,而RecyclerView的特性之一就是强制你使用它的RecyclerView.ViewHolder。可是,RecyclerView.ViewHolder要比我们写的那个单纯的容器复杂多了(源码里算上注释有大约500行),与RecyclerView.Adapter的联系也是千丝万缕。

按stackoverflow上面比较通俗的解释:RecyclerView.Adapter里面的onCreateViewHolder()方法和onBindViewHolder()方法对时间都非常敏感。类似I/O读写,Bitmap解码一类的耗时操作,最好不要在它们里面进行。

如何解决卡顿问题

首先当然得优化你的item,合理运用<include><merge><ViewStub>等标签,使布局层次尽量少——其实ListViewGridView里你也应该这么做,应该当成是一种写UI的习惯。

其次就是灵活使用各种第三方库,去完成各种耗时操作,比如通过Glide或者是Picasso加载图片。优秀的开源库在性能上往往都考虑得很仔细。

最后的问题来了,如果只想写一个小demo,不愿大张旗鼓怎么办?如果即便一般的第三方库也不好解决问题,比如上一篇那个该死的loadIcon()方法返回的是一个Drawable对象,Glide和Picasso都没法直接处理,转码又等于添了个耗时任务,那怎么办?
真正的app管理应用,应该引入UIL或者Picasso一类的加载库进行图标加载
(在此原谅博主没仔细敲代码,就信口开河了)
答案就是,想法在你setAdapter之前就把任务给完成

TimeCat 实例

1
2
3
4
5
6
7
8
9
10
11
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
context = getContext();
View view = inflater.inflate(R.layout.fragment_notes, container, false);

mStackView = view.findViewById(R.id.notes_csv); // 初始化RecycleView
cardStackViewAdapter = new CardStackViewAdapter(context); // 初始化Adapter
refreshData(); // 刷新一次数据
mStackView.setAdapter(cardStackViewAdapter); // 在数据准备好后再setAdapter()

return view;
}

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器