如何监测Android应用卡顿?这篇就够了

本文首发于微信公众号「开发之旅」 , 欢迎关注
版Wan-项目地址: 架构开发组件化应用实战 欢迎star
版Wan-项目地址:版Wan- 欢迎star
卡顿介绍
用户在使用我们应用的时候 , 很多问题是很难被及时的发现的比如内存占用高 , 耗费流量等 , 但是一旦发生卡顿就会被用户直观的感受到 。所以应用卡顿是很影响用户体验的 。另外一方面 , 对于开发者来说 , 卡顿的问题很难定位 , 发生问题的原因错综复杂 , 比如:代码问题、内存问题、绘制问题以及IO操作等等 。而且线上发生的卡顿问题在线下我们很难复现 , 因为这和用户当时的系统环境有很大的关系 , 因此我们需要在用户发送卡顿的时候记录下用户使用的场景等 。比如:内存消耗 , 磁盘空间 , 用户行为路径等等 。
优化工具 CPU
目前 以及自带了CPU 工具 , 它可以以图形化的形式展示执行的时间、调用栈等信息 。收集的信息比较全面 , 包含了所有线程 。但是由于其收集信息全面 , 导致了运行时内存开销严重 , App函数整体运行都会变慢 , 可能会带偏我们的优化方向 。
使用方式:
Debug.startMethodTracing();...Debug.stopMethodTracing();
最终生成的文件在sd卡:/data//files目录下 。
之前文章已经讲解过 , 它是轻量级的框架 , 而且开销小 , 可以直观反映CPU的利用率而且右侧alter可以针对一些问题给出相关的建议 。比如绘制慢或者GC频繁等 。
.3引入的一个工具类:严苛模式 。是一种运行时检测机制 。可以帮助开发人员检测代码当中不规范的问题 。主要检测线程策略和虚拟机策略 。
线程策略包括:
虚拟机策略:
我们在中使用:
private void initStrictMode() {if (BuildConfig.DEBUG) {//线程StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectCustomSlowCalls() //API等级11 , 使用StrictMode.noteSlowCode.detectDiskReads().detectDiskWrites().detectNetwork()// 或者直接使用 .detectAll() 手机全部信息.penaltyLog() //在Logcat 中打印违规异常信息 , 还可以选择弹框提示或者直接奔溃等.build());//虚拟机StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().setClassInstanceLimit(StrictModeTest.class, 1).detectLeakedClosableObjects() //API等级11.penaltyDropBox().build());}}
本身也是耗性能的 , 所以我们只在debug模式下开启 。当出现不符合检测策略的时候就会在控制台打印日志 , 输入关键词过滤即可 。
自动化检测卡顿方法
CPU和都是适合线下使用的 , 无法带到线上 。那我们如何做到线上监测卡顿呢?
我们都知道一个进程中只有个对象 , 我们通过查看源码发现 , 在其loop方法中的死循环中有个对象 , 在执行的时候打印了一个 to日志 , 执行完成的时候有打印了一个 to日志 。如:
public static void loop() {// ....省略开始代码...for (;;) {Message msg = queue.next(); // might blockif (msg == null) {// No message indicates that the message queue is quitting.return;}?// This must be in a local variable, in case a UI event sets the loggerfinal Printer logging = me.mLogging;if (logging != null) {//重点 开始打印logging.println(">>>>> Dispatching to " + msg.target + " " +msg.callback + ": " + msg.what);}// ...省略中间代码...if (logging != null) {//重点 完成打印logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);}?// ...省略最后代码...}}