What is ANR?
ANR 即 Application Not Responding,程序无响应异常。在 Android 系统中,当一个应用程序长时间没有响应用户操作的时候,就会弹出一个 ANR 异常提示框,提供用户退出当前应用的选择。弹出 ANR 提示框的应用程序的用户体验是相当差的,所以我们在写 Android 应用程序时,应该尽可能避免应用程序出现 ANR 异常。
什么时候会出现 ANR ?
在 Android 中,程序的响应性是由 Activity Manager 与 Window Manager 这两个系统服务来负责监控的。当系统监测到下面的条件之一时会显示 ANR 对话框:
- 对输入事件(例如硬件点击或者屏幕触摸事件),5秒内都无响应;
- BroadReceiver 不能够在 10 秒内结束接收到任务;
如何避免 ANR 异常?
- 针对第一类 ANR 异常:Android 系统中的所有操作默认都是在应用程序的主线程,即 UI 线程中排队执行的,那么当遇到一个相对比较耗时的操作,如网络请求、DB 操作、Bitmap 计算等,线程就会因为等待这些操作完成而无法响应用户事件,在等待时间超过 5 秒时,就会弹出 ANR 提示框。因此,针对这类 ANR 异常,通常的解决措施就是开启一个工作线程来执行耗时操作,等到操作完成时,再采用线程间通信方式将结果提交给 UI 线程加以显示。
- 针对第二类 ANR 异常:BroadcastReceiver 有特定执行时间的限制说明了 BroadcastReceiver 应该用于执行一些简短快速地任务,而不能用于执行耗时较长的任务。当需要执行耗时任务时,不同于第一类 ANR
异常,此时不是采用通过工作线程来执行复杂任务的方式,而应该发送一个 Intent 给 Service,由 Service 来执行该耗时任务。因为 BroadcastReceiver 的生命周期很短(在 onReceive() 执行后,BroadcastReceiver 的实例就会被销毁),而此时执行耗时操作的子线程很有可能还没有结束,若该子线程所在的宿主进程中还有其他组件正在运行的话,那么还好,若没有的话,那么该进程就属于一个空进程,其优先级很低,在系统内存较低的情况下,会最先被系统杀死。所以为了确保耗时任务能够顺利执行,应该使用 Service 来执行该耗时任务。
Tip: 可以使用 StrictMode 来帮助寻找因为不小心加入到 UI 线程的潜在的长时间执行的操作,例如网络或者 DB 相关的任务。
网友评论