我们以Activity为例,我们知道Activity的所有的生命周期都是运行在主线程的,为什么呢?
我们来看看哈。
ActivityThread内部成员变量mH,这个mH看下代码其实就是个Handler,它的类型是有ActivityThread的内部类H决定的。
我们来看看这个H的源码。
private class H extends Handler {
//定义了各种消息类型
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public s
tatic final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int NEW_INTENT = 112;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
…
…
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “activityStart”);
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
//启动Activity 最后会回调Acitivty的onCreate方法。
handleLaunchActivity(r, null, “LAUNCH_ACTIVITY”);
…
} break;
case RELAUNCH_ACTIVITY: {
…
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity®;
…
} break;
case PAUSE_ACTIVITY: {
…
//启动Activity 最后会回调Acitivty的onPause方法。
handlePauseActivity((IBinder) args.arg1, false,
(args.argi1 & USER_LEAVING) != 0, args.argi2,
(args.argi1 & DONT_REPORT) != 0, args.argi3);
…
} break;
…
…
}
}
看了H的代码,大多数朋友肯定都已经知道了。为什么Activity,Service这些组件的生命周期都是运行在主线程呢。其实都是与这个mH息息相关的。这个mH是与主线程的Looper对象进行绑定的,通过这个mH发送过来的消息都是执行在主线程的。Activity,Service这些组件的生命周期方法都是在mH的handlerMessage方法内部进行回调。这里解释一下哈,Android中我们所说的主线程其实就是ActivityThread的main方法所执行的线程,并不是ActivityThread本身哦。
所以换句话说检测主线程卡顿,我们只要检测每个消息执行的时长就可以了。Android内部其实已经为我们提供了一个方法,这就是BlockCanary的原理哦。
Handler机制我们最熟悉不过了,就不多说了,我们直接看看Looper.loop()方法实现,其中必有蹊跷。
public static void loop() {
…//省略部分代码
for (;😉 {
Message msg = queue.next(); // might block
if (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 logger
final Printer logging = me.mLogging;
if (logging != null) {
//第一次打印
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
try {
//分发消息,处理消息。target就是发送消息的Handler
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
…//省略部分代码
if (logging != null) {
//消息处理结束第二次打印
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
}
}
这里我们看到了重要的东西了哈,消息处理前会调用一个logging.println()方法,消息分发给Handler处理结束后,还会=调用一次logging.println()方法。这两次println()方法调用的时间间隔,不就是是我们主线程一条消息处理的时长么?那我们只要把logging这个对象替换程我们自己的不就好了嘛?
前面ActivityThread 的main方法中有一句这个代码: Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, “ActivityThread”));
这个方法干嘛的?其实就是set这个logging对象的!
我们来看看这个句代码:
public void setMessageLogging(@Nullable Printer printer) {
//直接把传进来的值,赋值给mLogging对象了
mLogging = printer;
}
public void setMessageLogging(@Nullable Printer printer) {
//直接把传进来的值,赋值给mLogging对象了
mLogging = printer;
}