由于项目中用到了RecyclerView。然后随着逻辑的增多,类型的增多,recyclerView的页面越来越卡顿。就项目中遇到的一些问题,自己做的一些优化,做一些记录,以及关于项目RecyclerView优化的一些想法也写下来。
卡顿原因
人眼看到的卡顿主要是由于帧的刷新率太低,达不到系统要求每秒16帧的效果,所以会感觉到卡顿。
安卓系统中的页面刷新主要是在主线程中执行的。所以主线程没有按时去刷新界面的话,就会造成卡顿的效果。 造成主线程卡顿的原因大概有以下几种:
- 主线程中执行的操作比较耗时
- 系统GC操作引起的主线程被挂起
- 重度绘制
原因查找:
要解决卡顿的问题,需要先定位到,引起卡顿的主要原因,采取对应的解决方案。
主线程中执行的耗时操作代码查找方式:
最简单直接的方法是在RecyclerView的 onBindViewHolder() 打印执行时间的日志,查看每个ViewHolder渲染所需要的时间。
long startTime = System.currentTimeMillis();
/**
要执行的代码
*/
long endTime = System.currentTimeMillis();
Log.e("tag", "time ="+ (endTime - startTime));
从日志中监测每个代码块的执行时间,建议每个View渲染的时间不超过20ms,如果有viewholder的渲染时间超过了50ms那这个页面就有很严重的卡顿现象了。
针对这种情况应该尽量减少在绑定数据的时候有耗时的操作,比如本地数据读取和保存,Inflater加载布局,bitmap的加载等等。如果需要有耗时的操作,则可以另启一个线程把耗时的操作放到子线程中。
系统GC操作引起的主线程被挂起:
当内存占用过多,或者系统中没有引用的对象数量太多时,会触发系统的GC操作,当系统gc的时候,会阻塞所有正在执行的线程,gc结束后会继续执行。但主线程被阻塞的时候,会引起卡顿。
系统GC操作的时候可以查看日志:
com.*.* I/art: Explicit concurrent mark sweep GC freed 704(26KB) AllocSpace objects, 0(0B) LOS objects, 4% free, 157MB/165MB, paused 421us total 58.448ms
重度绘制
重度绘制可以在手机的开发者选项中打开,如果有重度绘制的区域,屏幕会呈现红色。网上有很多关于重度绘制的,可以查找相关资料。