什么是ANR
ANR(Application Not responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完 成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR 在 Android 里,应用程序的响应性是由 Activity Manager 和 WindowManager 系统服务监视的。当它监测到以下 情况中的一个时,Android 就会针对特定的应用程序显示 ANR。
ANR的分类
- Service Timeout (服务)
- BroadcastQueue Timeout(广播)
- ContentProvider(内容提供者)
- Timeout InputDispatching Timeout (输入调度)
产生ANR的场景
- Service的startcommand()方法执行慢
- 在主线程中执行耗时操作(io操作、网络操作等)
- system_server进程的binder线程繁忙而导致没有及时收到拆炸弹的指令。
- 另外ActivityManager线程也可能阻塞, 出现的现象就是前台服务执行时间有可能超过10s。
不同机制下的超时时长
- 对于前台服务,则超时为SERVICE_TIMEOUT = 20s;
- 对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT = 200s
- 对于前台广播,则超时为BROADCAST_FG_TIMEOUT = 10s;
- 对于后台广播,则超时为BROADCAST_BG_TIMEOUT = 60s;
- ContentProvider超时为CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s;
- InputDispatching Timeout: 输入事件分发超时5s,包括按键和触摸事件。
注意:Input的超时机制与其他的不同,对于input来说即便某次事件执行时间超过timeout时长,只要用 户后续在没有再生成输入事件,则不会触发ANR(大部分人会说如果程序5s之内没有响应用户的事件就会产生ANR,这个是错误的说法)
如何避免ANR的产生
- 避免在主线程上进行复杂耗时的操作,比如说发送接收网络数据/进行大量计算/操作数据库/读写文件等。这个可以通过使用AsyncTask或者使用多线程来实现。
- broadCastReceiver 要进行复杂操作的的时候,可以在onReceive()方法中启动一个Service来处理
- 避免出现出现主线程和子线程出现同步/死锁或者错误处理不恰当等情况。
- 使用异步初始化替代一些三方框架的初始化,也可以使用splashActivity来做一个应用启动启动页来展示
- 为响应用户输入需要后台工作的话,可以显示工作的进度(ProgressBar和ProgressDialog)等。