简介
ANR,全称 Application Not Responding。中文称之为:程序无响应。
常见的ANR类型
- InputDispatching Timeout:屏幕触摸或键盘输入事件5s内无响应。
- BroadcastQueue Timeout :在执行前台广播(BroadcastReceiver)的
onReceive()
函数时10秒没有处理完成,后台为60秒。 - Service Timeout :前台服务20秒内,后台服务在200秒内没有执行完毕。
- ContentProvider Timeout :ContentProvider的publish在10s内没进行完。
解决方法
1.查看log
当程序发生ANR时,Logcat上会提示以下内容:
提示主线程中执行过多的耗时操作。
2.查看traces.txt
如果直接运行
adb pull /data/anr/traces.txt
会提示无该文件
adb: error: remote object '/data/anr/traces.txt' does not exist
所以,我们要先查看下/data/anr文件夹底下是不是真的没有该文件,还是说没有权限,无法拉取。依次运行以下命令:
adb shell
cd /data/anr
ls
界面显示
原来是真的没有该文件,写入的文件添加了包名+时间。所以,我们根据包名+时间可以更具体的知道是要拉取哪个文件。
Ctrl+d
adb pull /data/anr/traces_com.zr.leakcanarydemo_26_7月_11_36_37.786.txt
anr后的文件名称根据自己的实际情况修改。
以下摘要traces文件中的重要部分:
"main" prio=5 tid=1 Sleeping
| group="main" sCount=1 dsCount=0 obj=0x74891fa0 self=0x55861f4410
| sysTid=9634 nice=-1 cgrp=default sched=0/0 handle=0x7fa2e4dfe8
| state=S schedstat=( 139220744 1171927 192 ) utm=10 stm=3 core=6 HZ=100
| stack=0x7ffc139000-0x7ffc13b000 stackSize=8MB
| held mutexes=
at java.lang.Thread.sleep!(Native method)
- sleeping on <0x09c80e45> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:1031)
- locked <0x09c80e45> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:985)
at com.zr.leakcanarydemo.MainActivity$2.onClick(MainActivity.java:42)
at android.view.View.performClick(View.java:5207)
at android.view.View$PerformClick.run(View.java:21177)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5441)
at java.lang.reflect.Method.invoke!(Native method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)
从以上的信息中我们可以看出发生ANR的原因,以及发生ANR的具体函数行。而完整的traces文件还能看出:进程ID,包名等等。故我们可以根据提示去解决,就跟解决空指针一样,不用再像无头苍蝇一样。
这边需要注意的是Android设备差异比较大,本文在是小米手机上面操作的,部分手机在发生ANR是traces.txt文件是直接覆盖的,也不会在文件名中加包名和时间等等信息,故:还是需要到/data/anr文件夹底下查看后方能知道。
避免ANR技巧
- 不在主线程中做过多耗时操作
- 在异步线程中做文件读写或者数据库读写操作
- 注意各大组件ANR相应时间,不超过其阀值