/**
Handler、Looper、Message三者之间的关系,无外乎就是开始Looper会开始无限的循环,目的是在消息队列中进行获取Message,有则取无在等;而Handler则是在发送Message和handlerMessage方面起作用,发送的Message则是发送到消息队列中,handlerMessage则是处理Looper发过来的消息
*/
先附一张三者关系图方便理解
源码分析
首先我们来看一下Handler的构造方法
/**
* Default constructor associates this handler with the queue for the
* current thread.
*
* If there isn't one, this handler won't be able to receive messages.
*/
public Handler() {
...
//获取Looper对象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = null;
}
这里有一个判断,这里的判断主要的针对子线程new Handler的情况,因为在主线程Looper会自动创建在子线程里则没有。
为了验证我们来看主线程的方法ActivityThread类main方法
public static final void main(String[] args) {
...
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
...
}
}
Looper.prepareMainLooper()
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
public static final void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
if (Process.supportsProcesses()) {
myLooper().mQueue.mQuitAllowed = false;
}
}
从代码中可以看出其实main方法就是调用了prepare方法,而这个方法是将new Looper()放入ThreadLocal里面,所谓ThreadLocal类也HashMap是一样的,只不过它里面默认是将Key存储的每个线程,用途:保证每个线程所拥有的value是唯一的。ok,我们接下来看Handler的构造方法
Looper.myLooper()方法
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
这里只是将ThreadLocal类里面存入的Looper取出来,然后我们看ActivityThread类里面
Loop.loop()方法
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
...
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
msg.target.dispatchMessage(msg);
...
}
}
}
调用这个方法就进入了无限循环中,Looper将从MessageQueue中不断的取消息(有的时候则取没有的时候等待),当取到数据的时候会调用msg.target.dispatchMessage(msg)方法将Message回传到Handler中。target是什么呢?其实你顺着源码查看你会发现target其实是Handler对象,更准确的是该Message所属Handler对象。
msg.target.dispatchMessage(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);
}
}
这里的msg.callback和mCallback在Message和Handler创建的时候有相应的参数,这里最后的情况才是去执行handler的handlerMessage方法,这里需要注意喽,
如果你在Message和Handler里面使用Callback就不会在调用handlerMessage。
对于Looper取消息和发送消息就是这些,接下来来看一下Handler的发送消息到消息队列的过程
最终调用的sendMessageAtTime()方法
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
每次的发送中将当前发送的Handler对象赋值给target ,整好对应上面Looper取出Message之后根据target分发给相应的Handler的过程。
MessageQueue.enqueueMessage()方法
final boolean enqueueMessage(Message msg, long when) {
...
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked; // new head, might need to wake up
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
needWake = false; // still waiting on head, no need to wake up
}
}
if (needWake) {
nativeWake(mPtr);
}
return true;
}
在第一个if语句中通过比较传入的when和队列中第一个Message的when的大小,如果传入的小则需要马上进行处理,将needWake唤醒的状态置为true
否则的话将对消息队列进行遍历将传入的Message根据when插入到里面,并且将唤醒状态置为false。
到这里三者关系就大致讲完了,如果想了解更多请看鸿洋大神的: Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系