整体架构
创建Looper
在应用创建时,调用了ActivityThread的main方法,这个方法里面调用了Looper.prepareMainLooper();
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
这个方法里面调用了prepare方法,来创建Looper,并且将sMainLooper赋值为刚才创建的Looper。
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
prepare方法创建了Looper对象,并且存到sThreadLocal中。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Looper的构造方法是私有的,所以外部不能直接通过new构造出Looper对象。而且构造方法中加入判断,如果能取到Looper,则不能创建Looper了。 从而保证每个线程只能创建一个Looper对象。构造方法中初始了mQueue消息队列,将主线程mThread赋值为当前线程。 也就是ActivityThread.main方法执行的线程。最后在ActivityThread的main方法中执行了Looper.loop方法开启轮询。
创建Handler对象
Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
return false;
}
});
重写Handler的handleMessage方法或者重写Handler.Callback.handleMessage方法。二者不可得兼,因为二者方法签名一致。在Handler构造方法中, 将主线程的Looper赋值到全局变量mLooper中,将Looper的mQueue赋值到全局变量mQueue中。这也就是Handler的消息机制可以实现切换到主线程的原因。因为Handler处理消息的时候,是在主线程的 **Looper.loop()**中调用的。
public Handler(@Nullable Callback callback, boolean async) {
...
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
Looper.myLooper方法是从Looper的全局变量中mThreadLocal中取的的
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
发送消息
这么多发送消息的方法,不管是哪一个,最后都会走到enqueueMessage方法。queue的传值是全局变量mQueue,就是在构造方法中从Looper中传过来的队列。在enqueueMessage方法中,将msg.target设置为this,并且将消息入队。
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
在Handler的enqueueMessage方法中调用了MessageQueue 的enqueueMessage方法
boolean enqueueMessage(Message msg, long when) {
...
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
return true;
}
在MessageQueue 的enqueueMessage方法中,将传进来的msg赋值给全局变量mMessage中。等待被处理。
处理消息
处理消息的触发要回到Looper.loop方法,在这个方法里,有个死循环,不断从消息队列中取的消息。
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
...
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
...
}
}
取的消息之后,调用msg.target.dispatchMessage方法。 首先msg.target是一个Handler,在消息入队的时候enqueueMessage方法赋值的,将msg.target赋值为当前对象。然后就msg.target.dispatchMessage方法就会调用Handler的dispatchMessage方法。
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
}
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
如果msg.callback不为空,则执行handleCallback方法,调用msg.callback.run方法。最终调用Runnable的run方法。这就是Handler的post方法能切换到主线程运行的原因。 主线程创建的Handler,拥有主线程的Looper,拥有主线程的mQueue,所以post的时候,是将Runnable封装成Message对象放到主线程的mQueue中。
private static void handleCallback(Message message) {
message.callback.run();
}
这个msg.callback对象是在Handler.post方法中赋值的。
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
调用了getPostMessage®方法,将一个Runnable对象组装成一个Message对象。就是从池中取的一个Message,并且将callback变量赋值为传进来的Runnable对象。
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
回到Handler中dispatchMessage方法中,消息不是Runnable组装成的话,自然msg.callback会为null,这就走到了else分支。else分支又有一个条件判断,这次判断的是一个全局变量mCallback。mCallback是在构造的时候传入的,如果构造Handler的时候使用了这个构造方法public Handler(@Nullable Callback callback)
,则mCallback将被赋值,这里就会走到mCallback的handleMessage方法中。从代码上看Callback的handleMessage方法返回值要为true,才会走return语句,从而不调用Handler中的handleMessage方法。但实际上,不管Callback的handleMessage方法返回值是true还是false,都没有影响,因为Handler中的handleMessage方法默认是空实现,所以就算走了Handler中的handleMessage方法也没有关系。
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
public void handleMessage(@NonNull Message msg) {
}
总结
以上分析了Handler完整运行流程。 包括为什么能起到切换线程的作用,如果发送消息和处理消息的。可以说Handler、Looper、Message、Queue相辅相成,最终完成这样的机制。