异常——ANR
什么是ANR异常
ANR即Application Not Responding程序无响应,主要有以下三种情况会报ANR异常:
1、Activity的响应时间超过5s;
2、BroadcastReceiver执行时间超过10s;
3、Service执行时间超过20s;
造成ANR的原因
1、在主线程中执行了耗时操作,比如网络读取图片数据并进行图片转换;
2、在主线程中进行IO读写、磁盘读写、数据库读写等操作;
3、在主线程中大量创建新对象;
Android中执行在主线程的操作
1、Activity的所有生命周期回调方法;
2、Service默认是执行在主线程的;
3、BroadcastReceiver的onReceiver()回调方法;
4、没有使用子线程的looper的Handler的handlerMessage()方法,post(Runnable r)方法;
5、AsyncTask除了doInBackground()方法之外其它的方法都是执行在主线程中;
如何避免ARN
1、在UI线程中不要进行耗时操作;比如在Activity的onCreate()或者onResume()生命周期中不要做耗时操作;
2、创建子线程来执行耗时操作;
3、尽量使用Handler来处理主线程和子线程之间的交互;
4、可以使用AsyncTask来执行异步任务并及时更新UI;
如何排查ANR
1、查看报错的Log日志文件;具体可查看ANR的类型,CPU的使用情况等信息,并不能进行准确定位;
2、分析traces.txt文件;如果发生ANR异常,系统会在/data/anr/目录下生成traces.txt文件,可以通过分析traces.txt文件来查看产生ANR的原因,但前提是手机需要Root获取相应的权限;
3、使用BlockCanary第三方监控组件,BlockCanary可以对主线程进行完全透明的监控,而且如果遇到UI卡顿时能精确输出信息定位到问题所在,不需要像Logcat一样,慢慢去找。
BlockCanary的工作原理:
主要利用了主线程中的消息处理机制,在主线程中ActivityThread会默认创建一个Looper,而Looper会调用loop()方法不断从消息队列MessageQueue取出消息,然后通过dispatchMessage()方法进行消息的处理,通过ActivityThread的源码可以发现在dispatchMessage()方法的前后都有log输出事件,而dispatchMessage()是一次消息的处理过程,我们就可以计算从消息处理开始到消息处理结束的时间,如果这个时间超过了16ms的话,那么就可以认定是发生了UI卡顿现象,进而输出异常日志信息。
BlockCanary输出的信息:
(1)基本信息:安装包标示、机型、api等级、uid、CPU内核数、进程名、内存、版本号等;
(2)耗时信息:实际耗时、主线程时钟耗时、卡顿开始时间和结束时间;
(3)CPU信息:时间段内CPU是否忙,时间段内的系统CPU/应用CPU占比,I/O占CPU使用率;
(4)堆栈信息:发生卡慢前的最近堆栈,可以用来帮助定位卡慢发生的地方和重现路径;