Android 优化之卡顿优化的实现
Android系统每隔16ms会发出VSYNC信号重绘界面(Activity)。之所以是16ms,是因为Android设定的刷新率是60FPS(FramePerSecond),也就是每秒60帧的刷新率,约合16ms刷新一次。
这就意味着,我们需要在16ms内完成下一次要刷新的界面的相关运算,以便界面刷新更新。
假设我们更新屏幕的背景图片需要24ms来做这次运算,当系统在第一个16ms时刷新界面,由于运算还没有结束,无法绘出图片。当系统隔16ms再发一次VSYNC信息重绘界面时,用户才会看到更新后的图片。也就是说32ms后才看到了这次刷新(并不是24ms),这就是丢帧(droppedframe)。
丢帧给用户的感觉就是卡顿,而且如果运算过于复杂,丢帧会更多,导致界面常常处于停滞状态。
卡顿原因
过于复杂的布局
- 界面性能取决于UI的渲染性能,UI渲染的整个过程由CPU和GPU两个部分协同完成。CPU负责UI布局元素的Measure、Layout、Draw等相关运算执行,GPU负责栅格化(rasterization),将UI元素绘制到屏幕上。
- 如果UI布局层次太深,或是自定义控件的onDraw中有复杂运算,CPU的相关运算就可能大于16ms,导致卡顿。
过度绘制
UI线程的复杂运算
- UI线程的复杂运算会造成UI无响应,导致ANR,但更多的是造成UI响应停滞卡顿,ANR是卡顿的极致。
频繁的GC
优化方法
1、减少刷新次数
比如进度更新,要进度有变化再去刷新,且保证频率不得高于系统的刷新频率。
2、避免非必要的刷新
若控件不可见,则无需刷新。
3、避免后台线程影响
如列表控件,在滑动时不要去加载图片,可以在滑动监听里停止图片的加载。
4、局部刷新
如RecyclerView的DiffUtil。自定义View可以使用下面两个方法:
invalidate(Rectdirty); invalidate(intleft,inttop,intright,intbottom);
5、尽量使用属性动画,它减少了自身的重绘。最后要清除
StringBuilder,List等在创建时传入一个合适的参数指定初始容量,以避免频繁扩容的开销。
6、开启硬件加速
7、原理可见Android硬件加速原理与实现简介,理解Android硬件加速原理的小白文
Application级别
Activity级别
Window级别
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
View级别
//如果是software,会将View绘制到一个Bitmap, //然后依然是通过硬件加速将Bitmap绘制到Canvas view.setLayerType(View.LAYER_TYPE_SOFTWARE,null);
- LAYER_TYPE_NONE:普通渲染方式,不会返回一个离屏的缓冲,默认值。
- LAYER_TYPE_HARDWARE:如果这个应用使用了硬件加速,这个View将会在硬件中渲染为硬件纹理,如果应用程序并没有被硬件加速,则其效果和LAYER_TYPE_SOFTWARE相同。
- LAYER_TYPE_SOFTWARE:此View通过软件渲染为一个Bitmap。
检查是否开启了硬件加速
view.isHardware-Accelerated(); Canvas.isHardwareAccelerated();
如果View中要处理中文长文本,需要关闭硬件加速。因为每个中文编码不一样,缓存效果不理想。
监控
- 《Android应用性能优化最佳实践》2.8章,主要利用MainLooper里的Printer。
- BlockCanary开源库
- StrctMode
ANR
Activity的View:5秒无响应
BroadcastReceiver:10秒无响应
Service:20秒无响应
ANR时,系统会生成一个traces.txt的文件放在/data/anr/下。通过adb命令将其导出到本地
$adbpulldata/anr/traces.txt~/Desktop
UI线程做耗时操作,内存泄露导致内存不足都可能产生ANR。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。