什么是ANR
ANR(Application Not Responding)
就是通常我们在Andrid上遇到的程序无法响应问题。
如果APP的UI线程被长时间阻塞,就会触发ANR错误,如果我们的应用在前台运行,那么系统就会弹出对话框提示用户,允许用户强制结束程序。
如果应用在后台运行,默认不会弹出对话框;当然,我们也可以在系统设置中的开发者选项中,设置允许后台允许的程序也弹出ANR对话框。
ANR的触发
ANR是怎么产生的呢?
Android应用在UI线程(也叫主线程)中进行事件的分发处理、UI的刷新。当UI线程被阻塞,导致长时间无法处理用户输入或页面绘制,就会造成ANR,给用户的感知就是应用仿佛卡死了一般。
ANR的触发条件如下:
- 应用有activity在前台运行时,在5秒钟内无法对用户的输入(例如按键或触摸事件)或广播(
BroadcastReceiver
),做出处理 - 应用没有前台运行的activity时,如果广播(
BroadcastReceiver
)没有在一定时间内执行结束(官方文档没有给出具体时间)
Android vitals
Google提供了Android vitals工具来辅助提升应用的性能、稳定性等,遗憾的是需要Google Play框架的支持,这里暂时就不多介绍。
ANR的诊断
下面是一些通常的ANR产生的原因,我们可以沿着这些途径来诊断ANR:
- 在主线程中做了涉及IO的耗时操作
- 在主线程中做了耗时的大量计算工作
- 在主线程中使用了同步的binder跨进程调用,被调用的进程长时间未返回
- 在主线程中使用synchronized加锁,而锁已经被其它线程持有并长时间未释放
- 主线程和其它线程产生了死锁,可能是自身进程内产生的死锁,也可能是binder调用产生的死锁。
诊断技术
严格模式(Strict mode)
开启严格模式,能够辅助我们在开发阶段发现主线程IO等情况。我们可以在应用层级内或activity层级内开启严格模式。
开启后台ANR对话框
应用在后台运行时,默认不会弹出ANR对话框。我们也可以在系统设置中的开发者选项中,设置允许后台允许的程序也弹出ANR对话框,这样广播处理超时后就会弹出ANR提醒用户。
trace文件
Android在发生ANR的时候,会将相关信息记录到手机上。旧版本的Android会记录到/data/anr/traces.txt
文件中,新版本Android系统会记录多个文件:/data/anr/anr_*
。通过adb工具将文件取出分析:
$ adb pull /data/anr/<filename>