什么是Android ANR?
“ANR”是“Application Not Responding”的简写,即应用程序无响应。在Android中,ActivityManagerService(简称AMS)和WindowManagerService(简称WMS)会监测应用程序的相应时间,如果应用程序主线程(即UI线程)在超时时间内对输入事件没有处理完毕,或对特定操作没有执行完毕,就会出现ANR,Android会显示一个对话框,提示用户当前应用程序没有响应,用户可以选择继续等待或者关闭程序(即杀掉进程)。
出现ANR的条件
一、主线程:只有应用程序进程的主线程响应时间超时才会产生ANR
二、超时时间:产生ANR的上下文不同,超时时间也会不同,但只要在这个时间上限内没有响应就会ANR
三、输入事件/特定操作:输入事件是指按键、触屏等设备输入事件,特定操作是指BrodcastReceiver和service的生命周期中的各个函数,产生ANR的上下文不同,导致ANR的原因也不同
有一下三种情况会触发ANR:
1、主线对输入事件在5秒内没有处理完毕
当应用程序的Window处于Active状态并且能够接收输入事件(例如按键事件、触摸事件等)时,系统底层上报的事件就会被InputDispatcher分发给这个应用程序,应用程序的主线程通过InputChannel读取输入事件并交给界面视图处理,界面视图是一个树状结构,DecorView是视图树的根,事件从树根开始一层一层向端点(例如一个Button)传递。我们通常会注册一个监听器来接收并处理事件,或者创建自定义的视图控件来处理事件。
InputDispatcher运行在系统进程(进程名为system_server)的一个单独的线程中,应用程序的主线程在处理事件的过程中,InputDispatcher会不断的检测处理过程是否超时,一旦超时,会通过一系列的回调通知WMS的notifyANR函数,最终会调用到AMS中mHandler对象里的SHOW_NOT_RESPONDING_MSG这个case,此时界面上就显示系统提示对话框了,同时使用logcat命令查看log(日志信息)也可以看到关于ANR的信息。一下子出现了好几个重要的名词,要深入了解这种情况的ANR,需要熟悉Android的事件机制,本次不做解析,这里只需要记住他们的功能:
Window:具体指的是PhoneWindow对象,表示一个能够显示的窗口,它能够接收系统分发的各种输入事件;
InputDispatcher:将系统上报的输入事件分发给当前活动的窗口;
InputChannel:InputDispatcher和应用程序分别运行在两个不同的进程中,InputDispatcher就是通过InputChannel将事件对象传递给应用进程的。
注意:产生这种ANR的前提是要有输入事件,如果用户没有触发任何输入事件,即便是主线程阻塞了,也不会产生ANR,因为InputDispatcher没有分发事件给应用程序,当然也不会检测处理超时和报告ANR了。
2、主线程在执行BroadCastReceiver的onReceiver函数时10秒内没有执行完毕
BroadCastReceiver的onReceiver函数运行在主线程中,当这个函数超过10秒钟没有返回就会触发ANR。不过对于这种情况ANR系统不会显示对话框,而是仅仅输出log。
3、主线程执行Service的各个生命周期函数时,20秒内没有执行完毕
Service的各个生命周期函数也运行在主线程中,当这些函数超过20秒钟没有返回就会触发ANR。不会显示对话框,而是输出log。
三种ANR发生时都会在log中输出错误信息,你会发现各个应用进程和系统进程的函数堆栈信息都输出到了一个/data/anr/traces.txt的文件中。
这三种ANR不是独立的,会相互影响的。
网友评论