Handler是Android里面線程間通信的手段,它可以向自身持有的looper所在的線程發(fā)送消息進(jìn)行通信。
先看看典型的帶looper的線程的創(chuàng)建方法。
* 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的注釋
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call {@link #prepare} in the thread that is to run the loop, and then {@link #loop} to have it process messages until the loop is stopped.
上面注釋的大意是,Looper類用來(lái)給一個(gè)線程運(yùn)行消息循環(huán)。線程默認(rèn)情況下是沒有消息循環(huán)的。使用Looper.prepare方法和Looper.loop來(lái)運(yùn)行循環(huán)并且讓它處理消息。
可以看到上面的代碼和注釋的說(shuō)明是一致的,在thread的run方法中,先調(diào)用Looper.prepare方法來(lái)初始化looper,然后調(diào)用Looper.loop來(lái)運(yùn)行循環(huán),并且初始化了handler
看看Looper的初始化過(guò)程Looper.prepare
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
...
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
prepare方法new出了一個(gè)looper對(duì)象并把它放入了一個(gè)ThreadLocal變量,這樣每一個(gè)帶looper的線程將維護(hù)自己的一個(gè)looper對(duì)象。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
looper構(gòu)建的時(shí)候初始化了mQueue變量,它是一個(gè)MessageQueue對(duì)象。
再來(lái)看看Looper.loop()方法是如何運(yùn)行循環(huán)的
public static void loop() {
...
for (;;) {
Message msg = queue.next(); // might block
...
...
msg.target.dispatchMessage(msg);
...
}
}
loop()方法中,通過(guò)一個(gè)死循環(huán)不斷地通過(guò)調(diào)用MessageQueue的next方法獲取message,在注釋中可以看到,next方法可以被阻塞,如果沒有獲取到message就一直阻塞在這里直到獲取到為止。然后調(diào)用msg.target的dispatchMessage方法,這里的msg.target其實(shí)就是handler,dispatchMessage方法就是我們創(chuàng)建handler的時(shí)候重寫的dispatchMessage方法。
MessageQueue是一個(gè)典型的生產(chǎn)者/消費(fèi)者隊(duì)列,線程通過(guò)looper的loop方法不斷地消費(fèi)MessageQueue中的message,而生產(chǎn)者則是handler。
下面我們看看生產(chǎn)者h(yuǎn)andler是如何向MessageQueue發(fā)送message的。
先看看handler的創(chuàng)建過(guò)程,我們都知道不帶參數(shù)的handler創(chuàng)建的時(shí)候必須在looper線程內(nèi)創(chuàng)建,然后才能在其它線程中使用該handler向該線程發(fā)送消息,為啥要在線程內(nèi)創(chuàng)建呢?
public Handler(Callback callback, boolean async) {
...
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;
}
不帶參數(shù)的handler構(gòu)造器最終調(diào)用了上面這個(gè)構(gòu)造器??梢钥吹嚼锩嬲{(diào)用了
mLooper = Looper.myLooper();
這里的myLooper方法獲取的就是前面說(shuō)的存儲(chǔ)在TheadLocal變量里面的當(dāng)前線程的looper,然后又調(diào)用了
mQueue = mLooper.mQueue;
這里的mQueue就是上面說(shuō)的MessageQueue。
所以就很明顯啦,handler在哪個(gè)線程進(jìn)行初始化,就會(huì)持有哪個(gè)線程的looper以及該線程looper內(nèi)的MessageQueue,進(jìn)而就會(huì)把消息發(fā)送到該線程的looper內(nèi)的messageQueue。
事實(shí)上,Handler類是提供了帶Looper參數(shù)的構(gòu)造器的,使用這種構(gòu)造器就不需要在Thread的run方法內(nèi)部來(lái)初始化Handler了。
再來(lái)看handler發(fā)送message的過(guò)程,Handler的眾多sendMessage和post方法最終都會(huì)調(diào)用這個(gè)方法
public boolean sendMessageAtTime(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);
}
繼續(xù)跟進(jìn)
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
可以看到把msg.target設(shè)置為了this,這里的this就是handler對(duì)象自己。
然后調(diào)用了MessageQueue的enqueueMessage方法,跟進(jìn)去看看。
boolean enqueueMessage(Message msg, long when) {
...
synchronized (this) {
...
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里面維護(hù)了一個(gè)mMessages域,它是一個(gè)Message,可以看到Message是一個(gè)鏈表結(jié)構(gòu),enqueueMessage做的主要事情之一就是把message插入到mMessages中的合適位置。
這樣,通過(guò)enqueueMessage方法,message就被handler放到MessageQueue中了。
綜上,Handler的機(jī)制可以總結(jié)如下:
- Thread的run方法中,創(chuàng)建了一個(gè)ThreadLocal類型的域Looper。
- Looper又創(chuàng)建并持有一個(gè)MessageQueue。
- 然后Handler被創(chuàng)建并持有Looper和MessageQueue的引用。
- MessageQueue是一個(gè)生產(chǎn)者/消費(fèi)者隊(duì)列,Looper通過(guò)loop()方法中的死循環(huán)不斷地向隊(duì)列獲取Message,獲取到則調(diào)用Message所持有的Handler對(duì)象的dispatchMessage方法;如果獲取不到則阻塞在那里。
- 被創(chuàng)建出來(lái)的Handler對(duì)象可以被其它的線程所持有并且生產(chǎn)出Message發(fā)送到隊(duì)列中。