new Handler().obtainMessage().sendToTarget()這句話用著真爽,一行代碼就能搞定異步消息了!所以在代碼中使用的算是非常頻繁的了,那這又是一個什么樣的過程呢? 這個過程中又有什么玄機呢? 這篇文章,我們來一步步的分析一下這三句話。
### 1、new Handler()的分析
new?Handler()會輾轉來到public?Handler(Callback?callback,?boolean?async)這個構造方法。在這個構造方法中會獲取當前Looper:
~~~
mLooper = Looper.myLooper();
~~~
而此時的Looper是默認的那個Looper,即在ActivityThread的main方法中prepare的Looper
在ActivityThread.main中:
~~~
Looper.prepareMainLooper();
...
Looper.loop();
~~~
此時Handler和Looper有了關聯。
### 2、obtainMessage()的分析
在Handler.obtainMessage()中會調用Message.obtain(this)。
Message.obtain()的源碼:
~~~
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
~~~
obtain從消息池中構造一個message,并將message的target置為傳進來的handler。
此時handler和message有了關聯。
### 3、sendToTarget()的分析
~~~
public void sendToTarget() {
target.sendMessage(this);
}
~~~
直接調用target.sendMessage,而target正是當前的Handler。
繼續跟蹤target.sendMessage(this) target中發送消息會輾轉來到private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)
在這個方法中有去調用queue.enqueueMessage.
繼續跟蹤queue.enqueueMessage,這個方法有點長,主要是將當前Message壓入消息隊列中:
~~~
...
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);
}
...
~~~
這里面的MessageQueue就是在Handler保存的那個MessageQueue,也就是說此時,這個Message已經保存到Handler中的那個消息隊列中了。而,我們Handler中的MessageQueue哪來的呢? 來看看這行代碼:
~~~
public Handler(Callback callback, boolean async) {
...
mLooper = Looper.myLooper();
...
mQueue = mLooper.mQueue;
...
}
~~~
Handler中的MessageQueue正式從Looper中獲取的,這個Looper當然就是在ActivityThread中prepare的那個。
順一下此時的關系:Handler中保存了ActivityThread中的Looper,并從該Looper中獲取了MessageQueue;調用obtainMessage,實質上是創建了一個Message對象,并將Message對象的target設置為現在的Handler;調用Message.sendToTarget()實際是調用了Message.target.sendMessage(),即Handler.sendMessage,而Handler.sendMessage會來到enqueueMessage方法,在這個方法中調用MessageQueue.enqueueMessage將消息壓縮剛開始我們獲取的那個MessageQueue。
此時,再來看看Looper.loop()是怎么將消息回調到handleMessage中的:
~~~
for (;;) {
Message msg = queue.next(); // might block
...
msg.target.dispatchMessage(msg);
...
msg.recycle();
}
~~~
繼續看看Handler.dispatchMessage():
~~~
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
~~~
轉來轉去,終于把Message回調到了handleMessage!!!
從源碼中,我們也能看出, sendToTarget()方法并不是真正的將Message發送出去,而是將Message壓入了MessageQueue中,真正去回調handleMessage還是在Looper.loop()中完成的。