继而调用sendMessagAtTime
方法:
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);
}
眼尖的小伙伴就会发现,等等不对,这代码中出了一个叛徒,啊不对,出了一个奇怪的东西。没错,就是刚才流程图中出现的这个MessageQueue
。你看,我没有胡说吧,这个MessageQueue
是实打实存在的,并且被作为参数一起传给了enqueueMessage
方法。其实无论你是如何使用Handler发送消息,结果都会走到enqueueMessage
方法中。
这是方法的调用链:
可以看到无论如何,最后都会走到enqueueMessage
方法中。这个enqueueMessage
方法具体做了什么事呢:
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);
}
enqueueMessage
一共做了两件事情,一个是给Message
赋值,一个是调用传进来的这个MessageQueue
的enqueueMessage
方法。注意啊,最后这个enqueueMessage
方法是在MessageQueue
中的,已经不再是Handler
的方法了,也就是说,调用走到了这里。事件的流向已经不归Handler
管了。
Handler::enqueueMessage
方法中第一行msg.target = this;
,这个this是什么呢?这个this
在handler
方法中自然是handler
本身了,也就是说这一行代码将handler
自身赋值给了Message
对象的target
字段。我们可以看以下这个target
字段的定义:
//简化后的代码
public final class Message implements Parcelable{
@UnsupportedAppUsage
/package/ Handler target;
}
啊,这样明白了,也就是说每个发出去的Message
都持有把它发出去的Handler
的引用,对不对?
没错事实就是这样,每个发出去的Message
对象内部都会有个把它发出去的Handler
对象的引用,也可以理解Message
这么做的目的,毕竟Handler
把它发射出去了,它不得知道是谁干的,好随后找它报仇么。那么我们继续下一步,msg.setAsynchronous(true)
这一行代码是设置异步消息的,这里暂时先不管它。我们先看queue.enqueueMessage(msg, uptimeMillis)
这行代码。也就是从这行代码,Message
就可以和Handler
说拜拜了您讷。
MessageQueue
Handler
这个mQueue
就是上文我们提到过的MessageQueue
对象,在上面的介绍说也说了,这货就是个骗子,明明起名是Queue
,却是单链表。你可能误会Google工程师了,名字也确实没什么错了,从机制上看确实很像队列。队列是什么特性啊,先进先出对吧。这个先后就是按时间来划分的,时间靠前的就在前面时间靠后的就在后面。而在这个单链表中也确实是这样实现的,按照时间的先后排序。这个就先不多讲了,一会讲如何实现的消息延时发送的时候会讲到这个。
到这里你可能有疑惑了,这个MessageQueue
是什么鬼,从哪里冒出来的。你可能还记得,在上面的sendMessageAtTime
方法中有这么一行:
MessageQueue queue = mQueue;
那么这个mQueue是在哪里被赋值的呢?当然是在构造方法中啦~
public Handler(@Nullable Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
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;
}
不对啊, 你TM骗我,在最开始你继承的Handler可没有这几个参数。哎呀,小伙子别心急,你看这个无参构造方法不也调用的这个方法么。
public Handler() {
this(null, false);
}
在这个有参数的构造方法中呢,可以看到有这么两行:
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;
我们在Handler
中使用的mQueue
就是在这里赋值的。这里的赋值可不简单,它拿的是人家Looper
的MessageQueue
作为自己的MessageQueue
,**而且在上面的代码中有一个很关键的点,就是调用Looper.myLooper()方法中获取这个Looper对象,如果是空的话就要抛出异常。**这一点非常关键,我们先做个记号,一会回过头来会看这一行代码。你就会明白它的作用了。
现在先不研究Looper
,我们继续看我们的MessageQueue
。上面说到,最后发送消息都调用的是MessageQueue
的queue.enqueueMessage(msg, uptimeMillis)
方法。现在我们已经拿到了queue
,进去看看这个方法它做了什么。
// MessageQueue.java
//省略部分代码
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
//【1】拿到队列头部
Message p = mMessages;
boolean needWake;
//【2】如果消息不需要延时,或者消息的执行时间比头部消息早,插到队列头部
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 {
//【3】消息插到队列中间
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()) {
<