ANR
ANR(Application Not responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。在 Android 里,应用程序的响应性是由 Activity Manager 和 WindowManager 系统服务监视的。当它监测到以下情况中的一个时,Android 就会针对特定的应用程序显示 ANR。
场景
Service Timeout、BroadcastQueue Timeout
ContentProvider Timeout 、InputDispatching Timeout
Timeout时长
对于前台服务,则超时为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。
如何避免ANR
主线程尽量只做UI相关的操作,避免耗时操作,比如过度复杂的UI绘制,网络操作,文件IO操作;
避免主线程跟工作线程发生锁的竞争,减少系统耗时binder的调用,谨慎使用sharePreference,注意主线程
执行provider query操作。
如何解决ANR
线下可以通过ADB命令导出ANR文件进行分析。
导出ANR文件
ANR发生之后我们可以使用以下命令导出ANR文件
1 | adb pull data/anr/traces.txt 存储路径 |
ANR文件分析
查看trace信息,分析是否有耗时的message,binder调用,锁的竞争,CPU资源的抢占。
如何监控ANR方案
线上监控方案我们可以实现FileObserver去监听ANR目录的变化和使用ANR-WatchDod去监听并打印ANR堆栈信息。
FileObserver
注意事项:
- FileOberver需要三种权限
1 | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> |
- FileOberver的startWatching、stopWatching都加锁,因此要避免在对象锁中实现,以免造成死锁。
使用方法:
1 |
|
ANR-WatchDog
ANR-WatchDog,是一个非侵入式的ANR监控组件。
使用步骤:
1 | implementation 'com.github.anrwatchdog:anrwatchdog:1.4.0' |
在application中使用
1 | class MyApplication: Application() { |
原理
与Watchdog原理类似,ANRWatchDog 继承子Thread,所以它最重要的就是run方法。核心内容可以分为以下几点:
- 在run方法中实现无限循环
_tick自动加上5000毫秒并往Handler发消息- 睡眠5000毫秒
- 如果5000毫秒之内主线程还没有处理Runnable,将_tick置0,则进入ANR异常。
Watchdog机制总结
每一个线程都可以对应一个Looper,一个Looper对应一个MessageQueue,所以可以通过向MessageQueue中post检测任务来预测该检测任务是否被及时的执行,以此达到检测线程任务卡顿的效果,但是前提是该线程要先创建一个Looper。
ANR异常我们可分为线上监测和线下监测两个方向
- 线上监测主要是利用FileObserver进行ANR目录文件变化监听,以ANR-WatchDog进行补充。
- FileObserver在使用过程中应注意高版本程序不可用以及预防死锁出现。
- 线下监测主要是在报错之后利用ADB命令将错误的日志导出并找到错误的类进行分析