美文网首页Android开发Android开发经验谈Android技术知识
Android卡顿优化 | ANR分析与实战(附ANR-Watc

Android卡顿优化 | ANR分析与实战(附ANR-Watc

作者: 凌川江雪 | 来源:发表于2020-04-05 17:39 被阅读0次

    本文要点

    • ANR概述
    • 发生ANR后Android系统的执行流程
    • ANR-WatchDog原理与实战
    • ANR的传统解决套路
    • ANR模拟实战
    • 线上ANR监控方案【ANR-WatchDog原理分析】
    • ANR-WatchDog实战
    • ANR-WatchDog总结
    • ANR-WatchDog与AndroidPerformanceMonitor的区别

    项目GitHub

    ANR概述

    • KeyDispatchTimeout,5s
      即按键或者触摸事件,在特定的时间(一般5s)之内没有响应;

    • BroadcastTimeout,前台10s,后台60s
      BroadReceiver 在特定的时间(一般前台10s,后台60s)之内没有响应完成;

    • ServiceTimeout,前台20s,后台200s
      Service 在特定的时间(一般前台20s,后台200s)之内没有处理完成;

    发生ANR后Android系统的执行流程

    • APP发生ANR
    • 进程接收异常终止信号,开始写入进程ANR信息(当时场景,包含当前线程所有堆栈信息、CPU/IO的使用情况等);
    • 弹出ANR提示框,提示用户关闭APP或者继续等待;(不同ROM表现不同,有的手机厂商会去掉这个提示框)

    ANR的传统解决套路

    • 【线下】在AS的Terminal中,使用
      adb pull data/anr/traces.txt 要存储在本地的路径
      导出上面提到的ANR现场信息文件
      导出来后,便可对文件内容进行详细分析:从CPU、IO、锁冲突等原因思考;

    ANR模拟实战

    • 模拟ANR原因:锁冲突;

      更改代码: 运行程序,等到程序ANR或崩溃,
      在Terminal使用刚刚提到的命令,导出ANR的信息文件: 生成文件: 打开文件,可以找到原因: 上次的BlockCanary同样捕捉到原因:

    线下套路其实就是在APP发生ANR时,
    导出信息文件,
    查看文件,结合代码进行分析;

    线上ANR监控方案

    • 通过FileOberver监控上述的ANR信息文件的变化,
      如果这个文件发生了变化,那就说明发生了ANR,
      那便可以把它上报到服务器,进行详细的分析;
      【高版本需注意权限问题】

    • ANR-WatchDog

      • 依赖compile 'com.github.anrwatchdog:anrwatchdog:1.4.0'
      • 官网 https://github.com/SalomonBrys/ANR-WatchDog
      • 原理(源码分析):ANRWatchDog本身就是Thread的子类:
        ANRWatchDog中,用一个绑定了主线程Looper的Handler,
        去处理_ticker【一个Runnable任务单元】;
        任务单元对一些值进行了处理,如_tick_reported _tick在初始为ANRWatchDog的全局变量时,被赋值为0;^^^^^^^^^^^^^^^^^
        ANRWatchDogrun()中,
        首先被利用去判定_ticker被post没有(因为一开始就_tick为0的话说明_tick还没被post),
        没有便将_tick=加上卡顿周期,之后post了_ticker
        此时_tick不为0!!^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        _ticker中的run(),再一次将_tick置零;^^^^^^^^^^^^^^^^^^^^^^^^^^
        所以只要_ticker不被处理,其run()便不会执行,
        _tick就不会被置零,
        由此根据_tick的值可以判断_ticker是否被处理了;
        _tick重新归零则主线程处理了_ticker
        _tick不为零则判定主线程卡顿,它没处理_tick!!!!!!!!

        ANRWatchDogrun()中,
        用刚说的主线程Handler,post了_ticker这个任务,
        然后自己sleep一段时间【即一个卡顿周期,稍后细说】,
        如果sleep结束之后,如果_tick != 0 && !_reported
        则说明主线程还没有处理_tickerrun()
        没有处理_ticker这个任务单元,
        那便认为主线程发生了卡顿【如源码注释所示】:!!!!!!
        确定发生了卡顿,就开始封装一个ANRError,进行后续处理了: 另外补充一下,
        ANRWatchDog提供了两个重载的构造器,
        提供给开发者对卡顿判定周期进行设置,开发者不设置则使用默认配置
        【跟BlockCanary同一个德行】 接着仔细看ANRError的构造流程 这里是有两种构造方式New()NewMainOnly(),其最终处理都差不多,
        就是通过mainLooper拿到主线程,
        再通过主线程拿到现场的堆栈信息
        最后返回构造好的ANRError实例: 拿到ANRError实例之后,
        通过_anrListener.onAppNotResponding(error);回调机制处理ANRError实例;
        回调机制就妙啊!^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        刚刚的_anrListener.onAppNotResponding(error);只是一个应用层上的调用;
        onAppNotResponding()的实现方式暴露给开发者了,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        在外部可以通过setANRListener()自己定制包含不同处理方式的ANRListener
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 开发者不定制,则使用框架自带的默认处理方式呗:
        处理方式简单粗暴哈,直接把ANRError丢出去,
        这样APP就直接崩溃了: ANRError乃是Error的子类:

    ANR-WatchDog实战

    • 引入依赖
    • 初始化ANR-WatchDog:
    • 还是上面那个项目,手动阻塞60s,
      运行程序,
      程序会5s后崩溃【5s是默认周期时间,崩溃操作见上面源码分析】
      logcat定位关键字fatal,可以看到ANRError打印的信息,
      信息中包括了崩溃现场所有线程堆栈信息
      以及显示bug代码的位置

    优化:
    当然默认的APP崩溃处理法并不妥当,
    影响用户体验,
    实际开发中,
    我们可以自己定义ANRListener,自定义处理方式【上面说过了】,
    把堆栈信息上报给服务器就是了!!!!

    总结

    • 非浸入式
    • 弥补高版本无权限问题

    与AndroidPerformanceMonitor的区别

    • AndroidPerformanceMonitor:
      原理是基于Handler-Message机制,
      监控主线程每一个Message的执行,
      在每一个Message的分发执行前后,进行信息处理;
      (不足:
      一般没有阻塞的情况下,
      每一个Message的执行时间是非常短暂的,
      达不到ANR的级别;
      而且InputEvent在queue.next中block,不会继续执行dispatchMessage,
      而是从native回调给InputEventReceiver.dispatchInputEvent处理分发,
      所以BlockCanary也就无法监控到这类ANR)
    • ANR-WatchDog:
      不管主线程是怎么执行的,
      只管最后的结果,
      我sleep一个周期之后,就要看我_tick值有没有被修改,
      没被修改就是ANR!
    • AndroidPerformanceMonitor适合全程监控卡顿,
      ANR-WatchDog适合补充ANR监控;
      两者可以相辅相成,结合使用!




    参考:

    相关文章

      网友评论

        本文标题:Android卡顿优化 | ANR分析与实战(附ANR-Watc

        本文链接:https://www.haomeiwen.com/subject/lroephtx.html