本文要点
adb pull data/anr/traces.txt 要存储在本地的路径
导出上面提到的ANR现场信息文件
;
导出来后,便可对文件内容进行详细分析:从CPU、IO、锁冲突
等原因思考;运行程序,等到程序ANR或崩溃, 在Terminal使用刚刚提到的命令,导出ANR的信息文件:
生成文件:
打开文件,可以找到原因:
上次的BlockCanary同样捕捉到原因:
线下套路其实就是在APP发生ANR时, 导出信息文件, 查看文件,结合代码进行分析;
FileOberver
监控上述的ANR信息文件的变化,
如果这个文件发生了变化,那就说明发生了ANR,
那便可以把它上报到服务器,进行详细的分析;
【高版本需注意权限问题】compile 'com.github.anrwatchdog:anrwatchdog:1.4.0'
ANRWatchDog
本身就是Thread
的子类:
ANRWatchDog
中,用一个绑定了主线程Looper的Handler,
去处理_ticker
【一个Runnable任务单元】;
任务单元对一些值进行了处理,如_tick
、_reported
:
_tick
在初始为ANRWatchDog
的全局变量时,被赋值为0;^^^^^^^^^^^^^^^^^
在ANRWatchDog
的run()
中,
首先被利用去判定_ticker
被post没有(因为一开始就_tick
为0的话说明_tick
还没被post),
没有便将_tick
=加上卡顿周期
,之后post了_ticker
;
此时_tick
不为0!!^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ticker
中的run()
,再一次将_tick
置零;^^^^^^^^^^^^^^^^^^^^^^^^^^
所以只要_ticker
不被处理,其run()
便不会执行,
_tick
就不会被置零,
由此根据_tick
的值可以判断_ticker
是否被处理了;
_tick
重新归零则主线程处理了_ticker
,
_tick
不为零则判定主线程卡顿
,它没处理_tick
!!!!!!!!
ANRWatchDog
的run()
中,
用刚说的主线程Handler,post了_ticker
这个任务,
然后自己sleep一段时间【即一个卡顿周期,稍后细说】,
如果sleep结束之后,如果_tick != 0 && !_reported
,
则说明主线程还没有处理_ticker
的run()
,
没有处理_ticker
这个任务单元,
那便认为主线程
发生了卡顿
【如源码注释所示】:!!!!!!
确定发生了卡顿,就开始封装一个ANRError
,进行后续处理了:
另外补充一下,
ANRWatchDog
提供了两个重载的构造器,
提供给开发者对卡顿判定周期
进行设置,开发者不设置则使用默认配置
:
【跟BlockCanary
同一个德行】
接着仔细看ANRError
的构造流程
这里是有两种构造方式New()
、NewMainOnly()
,其最终处理都差不多,
就是通过mainLooper
拿到主线程,
再通过主线程拿到现场的堆栈信息
,
最后返回构造好的ANRError
实例:
拿到ANRError
实例之后,
通过_anrListener.onAppNotResponding(error);
回调机制处理ANRError
实例;
回调机制就妙啊!^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
刚刚的_anrListener.onAppNotResponding(error);
只是一个应用层上的调用;
onAppNotResponding()
的实现方式暴露给开发者了,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
在外部可以通过setANRListener()
自己定制包含不同处理方式的ANRListener
:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
开发者不定制,则使用框架自带的默认处理方式呗:
处理方式简单粗暴哈,直接把ANRError
丢出去,
这样APP就直接崩溃
了:
ANRError
乃是Error
的子类:
logcat
定位关键字fatal
,可以看到ANRError
打印的信息,
信息中包括了崩溃现场所有线程
的堆栈信息
;
以及显示bug代码的位置
;
优化: 当然默认的APP崩溃处理法并不妥当, 影响用户体验, 实际开发中, 我们可以自己定义
ANRListener
,自定义处理方式【上面说过了】, 把堆栈信息上报给服务器就是了!!!!
_tick
值有没有被修改,
没被修改就是ANR!AndroidPerformanceMonitor
适合全程监控卡顿,
ANR-WatchDog
适合补充ANR监控;
两者可以相辅相成,结合使用!