官方文档中的定义:
What Triggers ANR?
- No response to an input event (such as key press or screen touch events) within 5 seconds.
对一个输入事件没能在5s内做出响应。 - A BroadcastReceiver hasn't finished executing within 10 seconds.广播接收器在10s内没能结束执行。
ANRs
- While your activity is in the foreground, your app has not responded to an input event or BroadcastReceiver (such as key press or screen touch events) within 5 seconds.当你的Activity处于前台,你的应用没有在5s内对一个输入事件或广播接收器做出响应。
- While you do not have an activity in the foreground, your BroadcastReceiver hasn't finished executing within a considerable amount of time.当你没有前台Activity,你的广播接收器在一个较长的时间里没能执行结束。
咦,普遍的说法是什么?
大概是这样的:
- 应用5s未响应输入事件
- 广播接收器10s未执行完成(即onReceive()方法返回。)
- 服务在20s内未执行完成。(其实应该说是onStartCommand()没有返回,因为服务的生命周期在onStartCommand()之后仍处于激活状态,只是我们一般都用线程,即使是不用线程,也将逻辑直接写在onStartCommand()里了。)
问题来了
- Activity中执行耗时任务,事件超过5s,会不会ANR?
- 广播接收器中到底能执行多久?
- Service中能执行多久?
第一个问题,是不是Activity中阻塞5s就会出现ANR?
Activity中阻塞60s在上边的测试中,我不断的增大Activity中阻塞的时间,直到60s时,如果不操作手机,仍然不会弹出ANR。
而如果在阻塞期间,你点击屏幕,就会在几秒中之内,弹出ANR。之所以说几秒而不是5s,因为大部分在6-7s左右,有时会到10s,这个我还要再研究一下。
证明了:是输入事件未得到响应引发的ANR,而不是主线程阻塞引起的(虽然主线程阻塞会导致接下来出现的输入事件得不到响应,进而引发ANR)。
第二个问题,广播接收器中到底能执行多久?
这是在后台执行的情况:
Receiver阻塞30s Receiver仍然没有ANR可以看到30s没问题,后续加到60s时也没问题,但到90s时,可以从调试器看到进程死掉。但不会有ANR出现。
那前台呢?
我把发送广播的应用的代码改一下,广播延时5s执行。这时候我会打开接收广播的应用。
Handler().postDelayed(
{ sendBroadcast(intent) }, 5000)
Receiver处于前台
第一个log是我确认延时没问题,第二个log是前台阻塞60s后打印的。嗯,阻塞60s没问题,前台后台都一样。
那Service呢?
我觉得看到这里,你可能觉得,Service也一样,只是阻塞主线程,如果没输入事件就不会导致ANR。
看我这个语气,你就知道事情没那么简单,经过多次测试,Service的onStartCommand()中阻塞20s以上,直接ANR。19s就没有问题,哇,你竟然按套路出牌了!
总结ANR出现的原因
- 输入事件没能得到及时的响应。因为广播接收器的onReceive()方法也是执行在主线程中的,所以也会阻塞主线程,导致之后的输入事件得不到响应。注意这个“之后的输入事件”,上边已经多次证明了,仅仅只是阻塞线程不会导致ANR
- Service的onStartCommand()方法20s内未返回。
使用的测试机信息:Sony Xperia Z5,Android7.1.1
网友评论