Looper日志检测卡顿检测是无法监控IdleHandler的queueIdle回调方法的,这个方法会在主线程空闲的时候被调用,主线程MessageQueue的queueIdle默认也在在主线程中执行,这里的耗时操作会阻塞在MessageQueue的next方法中,也会引起卡顿和ANR的。
//looper轮询消息
Message msg = me.mQueue.next(); // might block
//MessageQueue
Message next() {
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis);
//...
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
//IdleHandler的queueIdle
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
}
}
TracePlugin的IdleHandlerLagTracer就是解决这个问题的。TracePlugin启动时开启了IdleHandlerLagTracer
if (traceConfig.isIdleHandlerTraceEnable()) {
idleHandlerLagTracer = new IdleHandlerLagTracer(traceConfig);
idleHandlerLagTracer.onStartTrace();
}
@Override
public void onAlive() {
super.onAlive();
if (traceConfig.isIdleHandlerTraceEnable()) {
//创建自己的HandlerThread
idleHandlerLagHandlerThread = new HandlerThread("IdleHandlerLagThread");
//创建上报任务
idleHandlerLagRunnable = new IdleHandlerLagRunable();
//监控IdleHandler
detectIdleHandler();
}
}
@Override
public void onDead() {
super.onDead();
if (traceConfig.isIdleHandlerTraceEnable()) {
//onDead时移除消息
idleHandlerLagHandler.removeCallbacksAndMessages(null);
}
}
接着看下detectIdleHandler方法:
private static void detectIdleHandler() {
try {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
return;
}
//拿到主线程消息队列MessageQueue
MessageQueue mainQueue = Looper.getMainLooper().getQueue();
//通过反射拿到MessageQueue的mIdleHandlers,我们使用addIdleHandler的IdleHandler会存放在ArrayList<IdleHandler> mIdleHandlers
Field field = MessageQueue.class.getDeclaredField("mIdleHandlers");
field.setAccessible(true);
//创建自己的myIdleHandlerArrayList
MyArrayList<MessageQueue.IdleHandler> myIdleHandlerArrayList = new MyArrayList<>();
//将MessageQueue的mIdleHandlers替换成自己的myIdleHandlerArrayList,用来接管空闲消息
field.set(mainQueue, myIdleHandlerArrayList);
idleHandlerLagHandlerThread.start();
idleHandlerLagHandler = new Handler(idleHandlerLagHandlerThread.getLooper());
} catch (Throwable t) {
MatrixLog.e(TAG, "reflect idle handler error = " + t.getMessage());
}
}
通过反射拿到消息队列MessageQueue的空闲消息ArrayList,替换成自己的MyArrayList,然后在自己的MyArrayList的add和remove增加自己的逻辑来接管空闲消息。
static class MyArrayList<T> extends ArrayList {
Map<MessageQueue.IdleHandler, MyIdleHandler> map = new HashMap<>();
@Override
public boolean add(Object o) {
if (o instanceof MessageQueue.IdleHandler) {
//包装一层MyIdleHandler
MyIdleHandler myIdleHandler = new MyIdleHandler((MessageQueue.IdleHandler) o);
map.put((MessageQueue.IdleHandler) o, myIdleHandler);
return super.add(myIdleHandler);
}
return super.add(o);
}
@Override
public boolean remove(@Nullable Object o) {
if (o instanceof MyIdleHandler) {
MessageQueue.IdleHandler idleHandler = ((MyIdleHandler) o).idleHandler;
map.remove(idleHandler);
return super.remove(o);
} else {
MyIdleHandler myIdleHandler = map.remove(o);
if (myIdleHandler != null) {
return super.remove(myIdleHandler);
}
return super.remove(o);
}
}
}
包装一层MyIdleHandler,添加自己的逻辑且不改变原有逻辑。
static class MyIdleHandler implements MessageQueue.IdleHandler {
private final MessageQueue.IdleHandler idleHandler;
MyIdleHandler(MessageQueue.IdleHandler idleHandler) {
this.idleHandler = idleHandler;
}
@Override
public boolean queueIdle() {
//发送一个延迟2秒的消息
idleHandlerLagHandler.postDelayed(idleHandlerLagRunnable, traceConfig.idleHandlerLagThreshold);
//queueIdle的执行
boolean ret = this.idleHandler.queueIdle();
//如果不能在2秒后清空任务,说明queueIdle太慢了,则会执行上报。
idleHandlerLagHandler.removeCallbacks(idleHandlerLagRunnable);
return ret;
}
}
至此,IdleHandlerLagTracer卡顿监控分析完毕。