ANR(Application Not Responding)
ANR是由于主线程阻塞引起的,不过主线程阻塞不一定引起ANR,尝试在Activity的onCreate中进行无限循环,界面卡住了,主线程被成功阻塞,不过并没有ANR。这说明ANR是在一定的场景下才能出现的。
ANR出现的场景
Service ANR:Service Timeout是位于”ActivityManager”线程中的AMS.MainHandler收到SERVICE_TIMEOUT_MSG消息时触发。
对于Service有两类:
对于前台服务,则超时为SERVICE_TIMEOUT = 20s;
对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT = 200s
BroadcastQueue ANR:BroadcastReceiver Timeout是位于”ActivityManager”线程中的BroadcastQueue.BroadcastHandler收到BROADCAST_TIMEOUT_MSG消息时触发。
对于广播队列有两个: foreground队列和background队列:
对于前台广播,则超时为BROADCAST_FG_TIMEOUT = 10s;
对于后台广播,则超时为BROADCAST_BG_TIMEOUT = 60s
ContentProvider ANR:ContentProvider Timeout是位于”ActivityManager”线程中的AMS.MainHandler收到CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息时触发。ContentProvider 超时为CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s. 这个跟前面的Service和BroadcastQueue完全不同, 由Provider进程启动过程相关.
InputDispatching ANR:输入事件必须在5秒内处理完毕。在派发一个输入事件时,会判断当前输入事件是否需要等待,如果需要等待,则判断是否等待已经超时,超时就说明发生了ANR.
ANR的报告机制
对于Service, Broadcast, Input发生ANR之后,最终都会调用AMS.appNotResponding;
这个方法的职能就是向用户或开发者报告ANR发生了。 最终的表现形式是:弹出一个对话框,告诉用户当前某个程序无响应;输入一大堆与ANR相关的日志,便于开发者解决问题。
对于provider,在其进程启动时publish过程可能会出现ANR, 则会直接杀进程以及清理相应信息,而不会弹出ANR的对话框. appNotRespondingViaProvider()过程会走appNotResponding(), 这个就不介绍了,很少使用,由用户自定义超时时间.
Service,BroadcastQueue都是在AMS中埋炸弹的,然后客户端执行完生命周期之后,再向AMS中发送消息拆炸弹。如果超时没拆,那就beng,ANR了。原理其实就是Handler发一个延时消息,然后到时间还没remove掉就ANR。
参考链接: