問(wèn)題
Handler. post(Runnable r)的消息是如何傳遞的,傳遞了什么消息。
Post內(nèi)部將r對(duì)象轉(zhuǎn)化為消息發(fā)送到Handler所在線(xiàn)程的消息隊(duì)列中,執(zhí)行Looper.loop()方法的線(xiàn)程,將直接執(zhí)行r中的run()方法(注意沒(méi)有開(kāi)啟新線(xiàn)程,而是在Handler所在的線(xiàn)程中執(zhí)行的r中的run()方法)Handler在哪個(gè)線(xiàn)程創(chuàng)建,就在哪個(gè)線(xiàn)程運(yùn)行handleMessage(Message msg)。如何實(shí)現(xiàn)的綁定。
Looper.prepare()方法中將出初始化一個(gè)線(xiàn)程池,它能保證Looper與當(dāng)前線(xiàn)程一一對(duì)Looper的運(yùn)行機(jī)制
Looper.prepare()方法中進(jìn)行了線(xiàn)程池的初始化、創(chuàng)建消息隊(duì)列并將消息放在消息隊(duì)列中等操作(其中msg.targe屬性保存了Handler的對(duì)象),在調(diào)用Looper.loop()方法從消息隊(duì)列中取消息并調(diào)用Handler的dispatchMessage(Message msg)方法,在該方法中執(zhí)行handleMessage(Message msg)方法處理消息主線(xiàn)程如何利用Handler消息機(jī)制運(yùn)行handleMessage(Message msg)。
在創(chuàng)建Handler對(duì)象的線(xiàn)程中,Looper.loop()方法調(diào)用了Handler的dispatchMessage(Message msg)方法,在該方法中執(zhí)行了handlemessage(Message msg)主線(xiàn)程的Looper在哪定義的,handleMessage(Message msg)如何運(yùn)行到主線(xiàn)程中的。
ActivityThread的main()方法中首先執(zhí)行了Looper.prepare()方法,并在main()方法的最后執(zhí)行了Looper.loop()方法(該方法中執(zhí)行了handleMessage(Message msg)方法)
Handler的創(chuàng)建
Handler的默認(rèn)構(gòu)造方法如下:
public Handler() {
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 = null;
}
在Handler中沒(méi)有看到與當(dāng)前線(xiàn)程相關(guān)的綁定操作,唯一可能與此有關(guān)的便是mLooper = Looper.myLooper();這一句。于是查看Looper.myLooper()方法,其代碼如下:
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static Looper myLooper() {
return sThreadLocal.get();
}
這里主要用到的就是一個(gè)ThreadLocal,ThreadLocal是在Java.lang包里定義的一個(gè)工具類(lèi),其主要功能是為本地所有線(xiàn)程保存一個(gè)數(shù)據(jù)。ThreadLocal保證每個(gè)線(xiàn)程之間的數(shù)據(jù)相互獨(dú)立,一個(gè)線(xiàn)程相關(guān)數(shù)據(jù)的改變不會(huì)影響其他的線(xiàn)程數(shù)據(jù)。
在Looper類(lèi)中,當(dāng)ThreadLocal被有效初始化后,myLooper()方法將能夠有效的獲取當(dāng)前線(xiàn)程所對(duì)應(yīng)的Looper對(duì)象。那么Looper的靜態(tài)方法能夠通過(guò)其所執(zhí)行的線(xiàn)程方便的獲取此線(xiàn)程相關(guān)的Looper對(duì)象,使得Looper類(lèi)使用各靜態(tài)方法便能夠獲得與使用其對(duì)象一樣方便的使用方式。
ThreadLocal的初始化在Looper.prepare()中進(jìn)行。
在Looper. prepare()中將當(dāng)前線(xiàn)程相關(guān)的唯一的一個(gè)Looper對(duì)象與當(dāng)前線(xiàn)程進(jìn)行相關(guān)聯(lián),其代碼如下:
public static void prepare() {
prepare(true);
}
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));
}
因此,在使用Looper之前進(jìn)行prepare()(里面有ThreadLocal的初始化操作)將保證當(dāng)前線(xiàn)程擁有并只有一個(gè)Looper的對(duì)象與之相對(duì)應(yīng),在Handler創(chuàng)建時(shí)將獲取與此Handler想對(duì)應(yīng)的Looper。
至此,Handler與執(zhí)行線(xiàn)程的問(wèn)題解決。
Looper的運(yùn)行
雖然解決了Handler與線(xiàn)程以及Looper之間的關(guān)聯(lián)關(guān)系,但HandleMessage()究竟如何被相關(guān)線(xiàn)程執(zhí)行的問(wèn)題仍然沒(méi)有得到解決。
在Looper的API文檔中有如下記述:
一個(gè)典型的Looper線(xiàn)程如下所示。
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();
}
}
在執(zhí)行handleMessage(Message msg)線(xiàn)程中應(yīng)先執(zhí)行Looper.prepare()方法,并創(chuàng)建Handler對(duì)象,最后執(zhí)行Looper.loop()方法。因此,handleMessage(Message msg)方法應(yīng)該在Looper.loop()方法中以某種方式運(yùn)行。
Looper.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;
// 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 (;;) {
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);
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.recycle();
}
}
注意:調(diào)用loop()方法的線(xiàn)程與創(chuàng)建Handler對(duì)象的線(xiàn)程是同一線(xiàn)程。或者說(shuō),Handler創(chuàng)建的線(xiàn)程在沒(méi)有改變其指向的情況下,只能由該線(xiàn)程的loop()方法來(lái)處理傳遞給Handler的消息。
在通過(guò)myLooper()方法獲取了當(dāng)前線(xiàn)程對(duì)應(yīng)的Looper對(duì)象me后,使用me獲取了當(dāng)前線(xiàn)程所對(duì)應(yīng)的MessageQueue。然后進(jìn)入了一個(gè)由for定義的死循環(huán)。
在獲取了即將要處理的Massage msg后,執(zhí)行了msg.target.dispatchMessage(msg)。
msg.target是定義在Massage中的成員變量,類(lèi)型為Handler。指代此Message應(yīng)該由哪個(gè)Handler處理。因此,當(dāng)msg.target.dispatchMessage(msg)被執(zhí)行,將執(zhí)行此Message所對(duì)應(yīng)的Handler的dispatchMessage(Message msg)方法。
Handler中dispatchMessage(Message msg)方法定義如下:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
在不考慮msg擁有callback的情況下,要么執(zhí)行Handler的Callback接口中的handleMessage(msg),要么執(zhí)行Handler復(fù)寫(xiě)的handleMessage(msg)。
至此,handleMessage(Message msg)方法的調(diào)用地點(diǎn)可以確定。應(yīng)該是在與Handler對(duì)象創(chuàng)建的同一線(xiàn)程中,由其后的Looper.loop()方法進(jìn)行的調(diào)用。
主線(xiàn)程中的Looper
在正常編程的情況下,通常遇到的都是Activity的onCreate()方法、onStart()方法、onDestroy()方法等,他們就代表的主線(xiàn)程的使用,在這些方法中進(jìn)行UI界面的修改是被允許的,但主線(xiàn)程究竟是如何調(diào)用Looper.loop()的卻不得而知,因此需要查找Activity的實(shí)際啟動(dòng)地點(diǎn)才能得知主線(xiàn)程的真實(shí)樣貌及Looper.loop()方法調(diào)用位置。
在android.app包中查找ActivityThread類(lèi),其中在其源代碼最后定義了如下方法:
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在看到main方法的定義后,終于看到了Activity主線(xiàn)程的真實(shí)面目。這里對(duì)Looper進(jìn)行了當(dāng)前主線(xiàn)程的prepare并且在main方法的最后執(zhí)行了Looper.loop()方法,實(shí)現(xiàn)對(duì)當(dāng)前線(xiàn)程Handler.HandleMessage(Message msg)的調(diào)用。
至此,主線(xiàn)程的Handler.HandleMessage(Message msg)的調(diào)用問(wèn)題解決。
Handler. post(Runnable r)
關(guān)于pos()t方法究竟做了些什么,怎么以一個(gè)Runnable接口當(dāng)做Message消息發(fā)送給其它線(xiàn)程以及如何執(zhí)行。這些問(wèn)題還需要查看Handler. post(Runnable r)的源代碼,其源代碼如下:
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
根據(jù)源代碼所述,其post()方法也是通過(guò)某種形式將Runnable轉(zhuǎn)換為Message進(jìn)行消息的發(fā)送。而消息的獲取方式為getPostMessage(r),同時(shí)Runnable接口也是在這個(gè)方法中進(jìn)行處理的。getPostMessage(Runnable r)方法定義如下:
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
其中Message.obtain()是在消息池中獲取一條新的消息,即消息本身是空的。而Runnable接口r緊緊是將其設(shè)置給剛剛創(chuàng)建的新消息m的callback。
在獲取了消息并設(shè)置了callback后就用將這條消息send給消息隊(duì)列。這條消息的處理同樣在Looper.loop()方法中調(diào)用了Handler的dispatchMessage(Message msg)。再次給出dispatchMessage(Message msg)方法的代碼:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
可以看到,當(dāng)msg.callback非空時(shí),將會(huì)調(diào)用handleCallback(msg)。一下給出handleCallback(Message message)的代碼:
private static void handleCallback(Message message) {
message.callback.run();
}
在handleCallback(Message message)中直接調(diào)用了callback的run()方法。即在Looper.loop()方法執(zhí)行的線(xiàn)程中,直接執(zhí)行了Runnable所定義的線(xiàn)程。需要注意的是,這里并沒(méi)有啟動(dòng)新的線(xiàn)程來(lái)運(yùn)行Runnable接口,而是在Handler所在的線(xiàn)程中運(yùn)行。