在开发过程中发现页面卡顿的时就能在Logcat 中发现如下的日志
Skipped 30 frames! The application may be doing too much work on its main thread.
这个日志就是在提醒我们需要做性能优化,关于这个掉帧的具体由来可以查看我的另一篇博客 Choreographer 编舞者的艺术(https://www.jianshu.com/p/3650dc59976a) 中查看,这篇文章我们主要来说一下针对这种情况如何排查,
消息队列机制
image.png上面画的这张图片阐述了一种丢帧的可能,就是在屏障消息添加之前,我们向MessageQueue中添加了一些比较耗时的操作,导致消息屏障执行时机太晚,
在这个方向上我们就需要知道Looper 到底在处理哪一个消息,这个消息耗时了多久,其实这些东西在Looper的设计初衷时就给我们预留了后门,下面贴一下相关代码
public static void loop() {
final Looper me = myLooper();
// 省略代码....
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
final 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);
}
}
}
在looper 的loop 方法中他会轮序去处理消息,得到消息后,他会判断一下是否有Priner 来判断输出消息开始处理和结束处理的日志信息,我们可以通过这些东西来判断msg 处理是否合理
Choreographer 队列机制
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
刷新处理的时机也与 input 事件 动画等息息相关,如果在 Choreographer CallbackQueue 队列数组中的任意一个环节出现了执行时间过程,可能都会导致丢帧
从网上看过一些大神的文章,他们的做法是使用 反射的方式,在 doframe时向 CallbackQueue 数组中添加添加一个头部消息,这样数组中第一个消息处理的时机就是当前链表的开始时间,下一个头部既是下一组事件的开始时间,同时也是上一组事件的结束时间,来判断 这 4 个环节哪一个出现了问题,
第一个数据就代表的是 input 事件, 例如 event 等
第二个代表的是动画事件 复杂的动画,或者同一时间执行的动画比较多,可能导致丢帧
第三个代表的是插入动画事件
第四个代表的是整个绘制流程 从 performMeasure 一直到 onDraw 方法的耗时 ,这个节点经常出现问题
知道了在哪一个环节出现了问题,剩下的问题就比较好做了,
我遇到过的 就是 在onDraw 中 频繁的处理和销毁对象导致频繁的gc ,gc 的过程中为了保证指针的准确性 jvm 会 Stop The Word, 让整个系统都停一下,等待他处理完在继续工作,这就会导致丢帧
还遇到过布局层次不合理, 重复设置无用背景导致过度绘制 ,
也使用过canvas.clipPaht 来约束绘制边界来预防过度绘制等问题,
也遇到过在onCreate中确实需要初始化好多的控件,导致加载过慢,也可以使用 StubView 在请求结果后再inflate 控件,减少 在同一时间的工作量来达到优化的部分内容
也遇到过在打开activity 在onCreate中初始化复杂的动画,导致第一帧帧既要做动画,又要做一些测量 布局 绘制等工作导致的,在同一帧执行的任务比较多而导致的少量丢帧
应该还有其他的可以优化的点,但是我暂时就想到了这么多,如果你认为还有其他的,请联系我一起探讨,共同进步!
网友评论