ANR是什么
ANR全称 Application Not Response 程序未响应,是Android开发中最不能出现的Bug之一。
ANR的种类
ANR在Android中总共可以分为三大类
KeyDispatchTimeout
按键处理时间过长,或者按键处理长时间没有得到反馈 ,onClick onTouchEvent ... 最长5s
BroadcastTimeout
Broadcast 长时间未响应 10s
ServiceTimeout
Service 20s 未响应
ANR出现直观表现
ANR出现最直观的情况就是手机弹出一个框告诉你应用未响应。 但是这只能看出是前台的ANR 后台ANR是不能直接显示的 ,只有在开发者模式开启显示所有"应用程序无响应"才能捕获到后台的ANR
应用未响应.png
可能造成ANR的情况
- 应用在主线程上非常缓慢地执行涉及 I/O 的操作。
- 应用在主线程上进行长时间的计算。
- 主线程在对另一个进程进行同步 binder 调用,而后者需要很长时间才能返回。
- 主线程处于阻塞状态,为发生在另一个线程上的长操作等待同步的块。
- 主线程在进程中或通过 binder 调用与另一个线程之间发生死锁。主线程不只是在等待长操作执行完毕,而且处于死锁状态。如需更多信息,请参阅维基百科上的死锁。
ANR快速定位
分别从log日志上和data/anr/trace.txt快速定位到问题,下面用一个例子来进一步分析。
1 前台的keyDispatchTimeout
我在点击事件中特意让主线程Sleep10s 这样就会产生ANR
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val tx :TextView = findViewById(R.id.tx)
tx.setOnClickListener {
Thread.sleep(10000)
}
}
Log日志
有的时候的确会出现Anr in ..... 这种日志存在,但是不是每次ANR都会出现,唯一确定会出现的日志是
08-21 16:38:54.797 3610-3617/xx.xxx.xxxxxxxx I/art: Wrote stack traces to '/data/anr/traces.txt'
看到这个大概就能确认到对应的log文件在系统文件夹下的/data/anr/traces.txt中,
用adb 指令导出traces.txt到sdcard中,之后再导出到PC中查看
adb shell
adb cat /data/anr/traces.txt >mnt/sdcard/anr.txt
exit
adb pull sdcard/anr.txt F:\log
拿到Log日志之后直接查找关键字[com.xx.xxxxx]找到对应包名下,
at cn.xdf.myapplication.MainActivity$onCreate$1.onClick(MainActivity.kt:18)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
就直接定位到是Click事件出的问题。之后再从代码逻辑上改就行了。
总结
ANR 还有其他情况会造成,上文中的例子也是最简单的一种情况,更多的情况可能在实际操作时按情况解决,但是大体思路是没问题的。