用户触摸 *** 作InputEvent:5s内无响应触发ANR提示;
广播Broadcast:前台广播10s和后台广播60s会触发ANR;
服务Service:前台进程Service20s和后台进程Service200s会触发ANR;
而Service和Broadcast只会打印trace信息,不会提示用户ANRd窗,大部分可感知的ANR都是由于InputEvent引起的。
Android应用程序是通过消息来驱动的,Android某种意义上也可以说成是一个以消息驱动的系统,UI、事件和生命周期都和消息处理机制息息相关。Android的ANR监测方案也是一样,大部分就是利用了Android的消息机制。
InputEvent的ANR与上图有些不同,是在Native监控,但同样会堵塞主线程的消息队列。
一般来说有四种,分别为BlockCanay、ANR-WatchDog、SafeLooper和FileObserver。
BlockCanary一种非侵入式的轻量性能监控组件,原理巧妙的利用了Android原生Looper.loop中的一个log打印逻辑
这个log打印逻辑正是在Message消息分发前后,监控这两个逻辑之间的时间差就可以得到当前主线程的卡顿状态,如果超时则获取trace信息并上报,具体实现:
它的思路是开辟一个单独现场向主线程发送一个变量+1 *** 作,自我休眠自定义ANR的阈值,休眠过后判断变量是否+1完成,如果未完成则警告。
它主要是通过反射接管主线程Looper的功能,可以自由定制,但是进行message管理会有很大的性能损耗。
Android手机发生ANR后,会把信息存储在/data/anr/traces.txt文件,我们只需要监听这个文件的变化就可以知道是否发生了ANR。
在Android里,应用程序的响应性是由Activity Manager和WindowManager系统服务监视的 。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:
在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)
.BroadcastReceiver在10秒内没有执行完毕避免方法:
1、运行在主线程里的任何方法都尽可能少做事情。特别是,Activity应该在它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建 *** 作。(可以采用重新开启子线程的方式,然后使用Handler+Message的方式做一些 *** 作,比如更新主线程中的ui等) 2、应用程序应该避免在BroadcastReceiver里做耗时的 *** 作或计算。但不再是在子线程里做这些任务(因为 BroadcastReceiver的生命周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个 Service。(此处需要注意的是可以在广播接受者中启动Service,但是却不可以在Service中启动broadcasereciver) 3、避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)