阅读本文大概需要 5 分钟。
相对于其他类型的性能指标,卡顿是能直接让用户产生视觉反馈的现象,比如App反应滞后于用户的操作,在严重的情况下会出现ANR。关乎用户体验的大事,是很容易遭到用户吐槽的。因此,开发人员平时写代码时必须要时刻提醒自己不要落入卡顿的陷阱之中。
一. 卡顿原因
在罗列卡顿可能会发生的几个点之前,先简单介绍一下发生卡顿的原因。
在之前《handler系列》聊过,UI线程是基于queue中的message事件驱动的,事件 -> 执行 -> 下一个事件...,另一方面由于Android的帧率是60fps,也就是每16ms就会触发一次UI刷新,如果某个message的处理时间 > 16ms,就会导致接收到VSYNC信号的时候无法完成本次刷新操作,产生掉帧现象。
因此,从本质上来讲,我们必须让UI线程的任何事件在16ms之内解决战斗。
基于此,可能会导致卡顿的原因有三大类:
1)事件本身太耗时。
2)事件本身并不耗时,但需要等待别的地方返回耗时。
3)UI线程本身已经拿不到CPU资源来执行事件。
下面根据这三大类来分别具体细聊。
二. 耗时事件
这个很容易理解,就是把一些耗时业务逻辑直接写在了UI线程中,比如计算密集型的复杂计算,庞大的MD5计算,非对称RSA解密等。一般情况下,开发人员都不会犯这种错误,因为能够直接意识到计算量很大,本身就有警醒的作用。
三.耗时等待
1)网络I/O 同步请求
这种如果是在用以前比较老的网络库,比如URLConnection这种就需要开发人员自己来开启新的线程。开发者可能忘记开启子线程,又同时做了同步请求等待,导致卡顿的发生。但是现代网络库比如Okhttp,Retrofit已经帮我们准备好了线程池,一般不会再遇到。
2)磁盘I/O 文件,数据库
一般的文件和数据库操作,大家可能都会自觉的在子线程中操作。但是值得一提的是SharedPreference的存储和读取,根据sp的设计,创建的时候会开启子线程把整