从官方推荐的handler用法说起:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
先不管为什么要Looper.prepare(),直接看看handler的构造函数,new Handler会进入到下面的构造函数:
其中对looper有个判断,如果为null会发生runtimeException导致崩溃,这个looper正是从Looper的sThreadLocal中取出来的:
sThreadLocal是什么?
我的理解是,它保存了每个线程和它相关的Looper,通过sThreadLocal.get()就能得到looper,而sThreadLocal是个静态变量,直接在声明时就初始化了,所以我们在每个线程中直接使用Looper.myLooper()就能得到初始化handler需要的mLlooper(有点啰嗦了……)。
所以我们要先整一个looper和当前线程绑定,looper的作用是运行一个message loop来管理消息队列:
回到主线,有了looper,有了handler,我们可以发送消息了。sendMessage有好几种方式,sendEmptyMessage、sendMessage(message)、sendMessageDelayed()、sendMessageAtTime(),都会进入下面这个函数:
先对mQueue作了判断,mQueue是在handler构造函数里初始化的:
mLooper里的mQueue是在looper.loop()时初始化的:
所以如果没有调looper.loop()也会崩溃;handler发的消息会进入queue.enqueueMessage():
MessageQueue.enqueueMessage的代码:
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
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 {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
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并不是保存了所有的message,它只保留了一个message(虽然名字是mMessages):
从MessageQueue的dump方法可以看出一些端倪:
对MessageQueue的遍历,是通过保存的mMessage和message.netx实现的,并不是从一个集合中依次取出的。
再回到MessageQueue.enqueueMessage,一开始作了两个判断,然后是if-else:
if里面的作用,其实是做一个插队的操作,when代表每个msg发送的时间,MessageQueue里是按时间排序的,如果p == null说明当前没有处理消息,自然要把传进来的msg优先处理:保存为mMessages,并把next置为null,至于mBlocked先看看定义:
是next()操作是否阻塞的标志,传给needWake,然后判断needWake:
翻译一下就是,如果next()阻塞,调用native方法唤醒,没看native代码,我猜,next阻塞,说明没有其它消息需要处理,系统不会再去查询队列,会把队列查询功能暂时“休眠”起来,当队列更新时,要判断当前系统是否在处理消息,如果没有处理处于“休眠”状态,需要被唤醒;如果本来就在处理,就无需调用native方法去唤醒。
再来看else里面的代码:
看注释就知道了,当前MessageQueue有message,并且message的入队时间在传进来的msg前面,需要按照时间顺序把msg插入到队列中间:一个死循环,直到最后一个message的next为null,或者找到队列中时间在传进来msg之后的message,才跳出循环,把msg的next指向这个message(就是插队)。
if-else之后就是判断是否需要唤醒,然后调用native方法。
上面说的是前半部分,handler发消息,然后handler会调用MessageQueue的enqueueMessage方法,把消息加入队列。
后半部分,就是把消息从MessageQueue中取出来并处理。
在标准用法中,最后一行:
Looper.loop();
前面说过,“looper的作用是运行一个message loop来管理消息队列”,那么上面就是对消息队列的操作了。我把源码精简下,去掉打印的代码:
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
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
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...................................
msg.target.dispatchMessage(msg);
...................................
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
.....................................
msg.recycleUnchecked();
}
}
Looper在prepare时,就创建了一个MessageQueue:
handler就是把message发到了这个mQueue,在Looper.loop()里有个死循环,不断从中取出下一个message,如果message不为null:
msg.target.dispatchMessage(msg);
msg的target是什么?是个Handler类对象,什么时候赋值的?handler的enqueueMessage:
这里,message和发送它的handler绑定在一起,下面看看handler的dispatchMessage:
由于我们使用的时候,没有定义msg的callback,这里会进入else,判断mCallback,其实handler的mCallback也是没有定义的,最后到了handleMessage():
handler没有实现,是由子类实现的,所以回到了一开始定义一个Handler,并override handleMessage的地方:
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
总结一下,handler,MessageQueue,Looper在整个流程中的作用:
Looper.prepare():在当前线程绑定一个Looper,并初始化Looer中的MessageQueue;
new Handler:初始化一个handler并实现handlerMessage,用于处理消息,并在构造函数中,取出本线程Looper中的MessageQueue赋值给自己的成员变量mQueue;
handler.sendMessage:将message与handler绑定(msg.target = this),调用mQueue.enqueueMessage();
mQueue.enqueueMessage():MessageQueue对消息队列中的消息重新排序(其实没有队列,是修改message.next和mMessages);
Looper.loop():从当前线程中得到looper,(sThreadLocal.get()),取出looper中的mQueue,再用一个死循环从mQueue取出message(通过Message msg = queue.next()),得到message后,用它绑定的handler分发消息,(msg.target.dispatchMessage(msg)),dispatchMessage最终回到了new Handler时实现的handlerMessage。