Handler機(jī)制在android開(kāi)發(fā)中經(jīng)常使用,一直沒(méi)搞明白Handler,Looper,MessageQueue它們之間的關(guān)系,此次就從源碼的角度分析一下
1. 簡(jiǎn)述
Looper負(fù)責(zé)創(chuàng)建MessageQueue,然后進(jìn)入無(wú)限循環(huán)體中不斷從MessageQueue取出消息,觸發(fā)消息的分發(fā)處理,而Handler負(fù)責(zé)發(fā)送消息
2.源碼分析
- Looper
主要就是prepare和loop方法
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));
}
從上面看出ThreadLocal存儲(chǔ)了Looper對(duì)象,而且此方法不能運(yùn)行兩次,否則拋出異常.
loop()方法:
>public static void loop() {
final Looper me = myLooper(); //獲得Looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't
called on this thread.");
}
final MessageQueue queue = me.mQueue; //獲得MessageQueue
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) { //此處無(wú)限循環(huán),取出消息
Message msg = queue.next();
// might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg); //分發(fā)處理消息
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " +
msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to "+ msg.target.getClass().getName() + " " + msg.callback + "
what=" + msg.what);
}
msg.recycleUnchecked();
}}
首先myLooper()從ThreadLocal中獲取Looper對(duì)象,如果looper為null則拋出異常,也說(shuō)明prepare()在loop()之前運(yùn)行
>public static Looper myLooper() {
return sThreadLocal.get();
}
下一步是拿到MessageQueue,即me.Queue;
再進(jìn)入開(kāi)頭所說(shuō)的無(wú)限循環(huán),取出消息msg;
最后就是msg.target.dispatchMessage(msg),分發(fā)處理,target就是Handler.
概括Looper作用:
- 與當(dāng)前線程綁定,保證一個(gè)線程只會(huì)有一個(gè)Looper實(shí)例,同時(shí)一個(gè)Looper實(shí)例也只有一個(gè)MessageQueue。
- loop()方法,不斷從MessageQueue中去取消息,交給消息的target屬性的dispatchMessage去處理。
下面就該Handler發(fā)送消息了
- Handler
-
Handler與MessageQueue綁定
看Handler構(gòu)造方法public Handler() { this(null, false); } public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } 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 = callback; mAsynchronous = async; }
通過(guò)Looper.myLooper()獲取了當(dāng)前線程保存的Looper實(shí)例,然后又獲取了這個(gè)Looper實(shí)例中保存的MessageQueue(消息隊(duì)列),這樣就保證了handler的實(shí)例與我們Looper實(shí)例中MessageQueue關(guān)聯(lián)上了
下面看發(fā)送消息的方法
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
} `
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) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
此處調(diào)用了下面這個(gè)方法:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
nqueueMessage中首先為msg.target賦值為this,也就是把當(dāng)前的handler作為msg的target屬性。最終會(huì)調(diào)用queue的enqueueMessage的方法,也就是說(shuō)handler發(fā)出的消息,最終會(huì)保存到消息隊(duì)列中去。
現(xiàn)在已經(jīng)很清楚了Looper會(huì)調(diào)用prepare()和loop()方法,在當(dāng)前執(zhí)行的線程中保存一個(gè)Looper實(shí)例,這個(gè)實(shí)例會(huì)保存一個(gè)MessageQueue對(duì)象,然后當(dāng)前線程進(jìn)入一個(gè)無(wú)限循環(huán)中去,不斷從MessageQueue中讀取Handler發(fā)來(lái)的消息。然后再回調(diào)創(chuàng)建這個(gè)消息的handler中的dispathMessage方法,下面我們趕快去看一看這個(gè)方法:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
可以看到調(diào)用了 handleMessage(msg)方法;
public void handleMessage(Message msg) {
}
這是一個(gè)空方法,因?yàn)橄⒌淖罱K回調(diào)都是我們自己實(shí)現(xiàn)的,在handler中實(shí)現(xiàn)handleMessage();
好了,現(xiàn)在總結(jié)一下整個(gè)流程:
1、首先Looper.prepare()在本線程中保存一個(gè)Looper實(shí)例,然后該實(shí)例中保存一個(gè)MessageQueue對(duì)象;因?yàn)長(zhǎng)ooper.prepare()在一個(gè)線程中只能調(diào)用一次,所以MessageQueue在一個(gè)線程中只會(huì)存在一個(gè)。
2、Looper.loop()會(huì)讓當(dāng)前線程進(jìn)入一個(gè)無(wú)限循環(huán),不端從MessageQueue的實(shí)例中讀取消息,然后回調(diào)msg.target.dispatchMessage(msg)方法。
3、Handler的構(gòu)造方法,會(huì)首先得到當(dāng)前線程中保存的Looper實(shí)例,進(jìn)而與Looper實(shí)例中的MessageQueue想關(guān)聯(lián)。
4、Handler的sendMessage方法,會(huì)給msg的target賦值為handler自身,然后加入MessageQueue中。
5、在構(gòu)造Handler實(shí)例時(shí),我們會(huì)重寫(xiě)handleMessage方法,也就是msg.target.dispatchMessage(msg)最終調(diào)用的方法。
-
Handler post
一般使用方法
mHandler.post(new Runnable()
{
@Override
public void run()
{
Log.e("TAG", Thread.currentThread().getName());
}
});
看輸出結(jié)果,當(dāng)前thread就是handler所在線程,并不會(huì)單獨(dú)創(chuàng)建線程,看源碼: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;
}
可以看到就是將runnable設(shè)置為msg.callback,下面和handler.sendMessage一樣,最終到dispatchMessage:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
此時(shí)因msg.callback != null,所以直接執(zhí)行handleCallback(msg);
private static void handleCallback(Message message) {
message.callback.run();
}
handleCallback()其實(shí)就只執(zhí)行的Runnable的run方法,所以handler.post不會(huì)另開(kāi)線程;
嗯,到此就全部結(jié)束了,相信對(duì)Handler,Looper,MessageQueue之間的關(guān)系都有了解了吧.