上次我们谈到Handler和Looper关联,Looper又与主线程进行关联,所以Handler就与整个主线程中的消息队列进行了关联,接下来我们看一下消息是如何被处理的,代码如下:
/**
* 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;//1:获取消息队列
//代码省略
for (;;) {//这是一个死循环,消息循环
Message msg = queue.next(); // 2:消息逐个取出
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// 代码省略
msg.target.dispatchMessage(msg);//3:在Handler中处理消息
//代码省略
msg.recycleUnchecked();//4:回收消息
}
}
Looper总结:通过Looper.prepare()来获取Looper对象,消息队列封装在Looper对象中,并保存在sThreadLoal中,然后通过Looper中loop();死循环中,从消息队列中逐个去处理消息。
大家看到第3步中有一个msg.target.dispatchMessage(msg);msg是Message对象,而target则是Handler对象,源码如下:
public final class Message implements Parcelable {
/*package*/ Bundle data;
/*package*/ Handler target;
/*package*/ Runnable callback;
消息总结:说白了,消息就是转了一个圈,Handler将消息post给消息队列,消息队列又分发给Handler,
接下来我们看一下Handler中处理消息的方法
//消息处理,子类必须继承该方法
public void handleMessage(Message msg) {
}
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
dispatchMessage只是一个分发方法,如果Runnable类型的callback为空,则执行handlerMessage来处理,如果为空,则将更新UI的代码放在这里,如果callback不为空,则执行handlerCallBack来处理,则会调用Runnable中的run方法,这就是Handler消息分发的两种类型,当post(Runnable callback) 则callback不为空,当我们使用Handler来sendMessage时候,通常不会设置callback,也就执行了handlerMessage
public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
public final boolean sendMessageDelayed(Message msg, long delayMillis){
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
//代码省略
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//设置当前target为当前Handler对象
//代码省略
return queue.enqueueMessage(msg, uptimeMillis);//将当前对象插入到消息队列中
}
从上述代码可以看出,在post(Runnable callback)时会将Runnable包装成Message对象,最终会将消息插入到消息队列,此外sendMessage也是类似实现
总结:不管是哪种分发,Handler都会将消息追加到MessageQueue中,再经过不断循环,Android程序就运行起来了