一个是主线程有其它耗时操作,导致doFrame 没有机会在 vsync 信号发出之后 16 毫秒内调用;
还有一个就是当前doFrame方法耗时,绘制太久,下一个 vsync 信号来的时候这一帧还没画完,造成掉帧。
既然我们知道了卡顿的根本原因,那么我们就可以监控卡顿,从而可以对卡顿优化做到极致。我们可以从下面四个方面来监控应用程序卡顿:
- 基于 Looper 的 Printer 分发消息的时间差值来判断是否卡顿。
//1. 开启监听
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, “ActivityThread”));
//2. 只要分发消息那么就会在之前和之后分别打印消息
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException(“No Looper; Looper.prepare() wasn’t called on this thread.”);
}
final MessageQueue queue = me.mQueue;
…
for (;😉 {
Message msg = queue.next(); // might block
…
//分发之前打印
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
…
try {
//分发消息
msg.target.dispatchMessage(msg);
…
//分发之后打印
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
}
}
- 基于 Choreographer 回调函数 postFrameCallback 来监控
-
基于开源框架 BlockCanary 来监控
-
基于开源框架 rabbit-client 来监控
怎么避免卡顿:
一定要避免在主线程中做耗时任务,总结一下 Android 中主线程的场景:
-
UI 生命周期的控制
-
系统事件的处理
-
消息处理
-
界面布局
-
界面绘制
-
界面刷新
-
…
还有一