ANR的全称是application not responding,意思就是程序未响应。
首先ANR的发生是有条件限制的,分为以下三点:
1.只有主线程才会产生ANR,主线程就是UI线程;
2.必须发生某些输入事件或特定操作,比如按键或触屏等输入事件,在BroadcastReceiver或Service的各个生命周期调用函数;
3.上述事件响应超时,不同的context规定的上限时间不同
a.主线程对输入事件5秒内没有处理完毕
b.主线程在执行BroadcastReceiver的onReceive()函数时10秒内没有处理完毕
c.主线程在Service的各个生命周期函数时20秒内没有处理完毕。
如何找到anr的原因? 系统在发生anr时,会记录一个日志文件,也就是trace文件,这个文件里会记录 主线程中 哪个方法 执行 导致anr。 所以我们要拿到这个trace文件进行分析。 不同的手机trace文件的位置、命名管理方式可能略有差异。
方法一:adb pull /data/anr/traces.txt
这是早期的安卓系统 拉取trace 文件 的命令。这个命令在很机型上不能正常使用了,原因是各个厂商自行修改了trace文件的命名和管理方式。
方法二: 通过adb shell 进入到 “/data/anr/” 目录下,查看一下当前手机的命名管理方式。
adb shell :进入 shell命令模式
cd data :进入 data目录
cd anr:进入anr目录
ls -a :显示当前目录(即anr目录)下的所有文件
下图是我在小米5s plus 上运行的截图,我们可以发现 小米手机 是根据 就用的包名 和 anr发生的日期、时间 来命名的。 早期的trace.txt是将所有app的anr全都记录一个文件里,这样查找起来非常麻烦。 小米这项改进还是很有作用的。
trace文件的分析:引起ANR问题的根本原因,总的来说可以归纳为两类:
主线程阻塞、挂起、死循环
应用进程的其他线程的CPU占用率高,使得主线程无法抢占到CPU时间片
2.其他进程间接引起的,例如:
当前应用进程进行进程间通信请求其他进程,其他进程的操作长时间没有反馈
其他进程的CPU占用率高,使得当前应用进程无法抢占到CPU时间片
拿到trace文件后,直接根据自己应用的包名搜索关键信息, 在 main 线程中 调用 drawPolyline 时 发生 anr,大致可以猜测这个方法里 执行了 耗时操作, 而且消耗的时间达到5秒。
trace文件的具体分析,我这篇列举的不是很详细,请参考下面这篇博客,详细列举了几种常见的 anr 原因