1.首先看一段App應(yīng)用程序啟動的時候的源碼流程分析圖(網(wǎng)上看到的):

從上圖我們可以看到:當(dāng)我們點擊桌面的應(yīng)用程序的圖標(biāo)的時候,首先會通過Binder的IPC通信機制,啟動ActivityManagerService的startActivity方法,如果發(fā)現(xiàn)進程沒有啟動的話,需要通過zygote(受精卵)孵化出一個新的進程,在新的進程中執(zhí)行ActivityThread的main方法。
2.我們在獲取到Looper.getMainLooper()是通過sMainLooper來獲取的,那這個sMainLooper是在哪里賦值的?
答:首先我們看到在Looper中有一個方法prepareMainLooper(),該方法會對sMainLooper進行初始化,那么我們在什么時候會調(diào)用該方法呢,為什么我們在主線程中創(chuàng)建handler的時候,不需要手動去調(diào)用這個方法,而是直接利用handler的構(gòu)造方法,不需要對looper進行處理就創(chuàng)建呢?
細看framework的源碼,可以看到整個 Framework 框架只有兩個地方調(diào)用了 prepareMainLooper 方法:
第一處是在 SystemServer.java 中的 ServerThread,這個線程是在 Android 啟動過程中的 main() 方法啟動的:
public static void main(String[] args) {
new SystemServer().run();
}
public SystemServer() {
mFactoryTestMode = FactoryTest.getMode();
}
private void run() {
Looper.prepareMainLooper();
Looper.loop();
}
第二處是在 ActivityThread.java 的 main() 方法中:
public static void main(String[] args) {
......
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
Looper.loop();
}
因為systemServer是超級進程,是在系統(tǒng)啟動的時候,用來初始化各種系統(tǒng)核心服務(wù),是在不同于APP的進程中的。(從上面的分析來看的話,Android一個應(yīng)用開啟對應(yīng)一個進程,一個進程對應(yīng)有一個主線程。)根據(jù)下圖,我們可以明白是在App點擊時候的入口,ActivityThread中對sMainLooper進行賦值的。
3.為什么在子線程創(chuàng)建handler的時候,需要調(diào)用Looper.prepare()方法?
答:現(xiàn)在我們來看handler的構(gòu)造方法,對應(yīng)無Looper形參的構(gòu)造方法,都會執(zhí)行下面的構(gòu)造方法
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;
}
因為在Looper.prepare()會創(chuàng)建一個looper與當(dāng)前線程綁定。如果子線程沒有調(diào)用prepare方法的話,那個mLooper=null,就會出現(xiàn)上面的報錯了。為什么主線程不需要調(diào)用,從1中我們可以看到,在app進程創(chuàng)建的時候,會調(diào)用Looper.prepareMainLooper(),所以主線程就不用再調(diào)用一次了。
4.當(dāng)handler發(fā)送一個消息的時候,怎么將消息插到隊列中?
答:如果發(fā)送的是Runnable,不是一個消息,也會在代碼中轉(zhuǎn)成Message類型,然后最終會執(zhí)行handler的private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)方法:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
將消息插入到消息隊列當(dāng)中去。其中的queue是通過looper.mQueue獲取的意味著messageQueue和當(dāng)前的looper是綁定的,所以一個looper應(yīng)該是對應(yīng)一個messageQueue。
5.當(dāng)Message插入到MessageQueue當(dāng)中,系統(tǒng)是怎么通知到對應(yīng)的handler來執(zhí)行handlerMessage方法呢?
答:如果是在主線程創(chuàng)建Looper的話,默認(rèn)會調(diào)用Looper.loop()方法,會不停地從消息隊列中取出消息,如果消息隊列為空,則不循環(huán),此時釋放cpu,不會占用cpu資源,如果有消息的話,那就執(zhí)行msg.target.dispatchMessage(msg);實際上就是調(diào)用handler的dispachMessage方法,會調(diào)用handler的handleMessage方法。
6.在主線程中通過Looper.loop()死循環(huán),為什么不會對主線程造成阻塞呢?
答:因為在該方法中,Looper在創(chuàng)建的過程中,會創(chuàng)建對應(yīng)的MessageQueue對象,在構(gòu)造函數(shù)中,會調(diào)用JNI的方法nativeInit(),通過這個方法會在c++層創(chuàng)建NativeMessageQueue,同時NativeMessageQueue會創(chuàng)建一個Looper對象,這個Looper對象是通過pipe(管道)設(shè)計而成的,如果有消息則喚起讀線程,沒有消息則線程阻塞,釋放cpu資源。回看java層的Looper類的loop方法,Message msg = queue.next(),進入next方法,會執(zhí)行nativePollOnce(mPtr, nextPollTimeoutMillis),調(diào)用JNI層的nativePollOnce方法,會調(diào)用NativeMessageQueue的pollOnce(),內(nèi)部調(diào)用了c++層Looper對象的pollOnce(),該方法會調(diào)用pollInner(),pollInner()方法就是先通過epoll_wait()進入空閑等待狀態(tài),等待消息隊列的管道上的消息(IO事件)。如果有消息待處理(即管道上有IO寫事件發(fā)生,寫事件是EPOLLIN類型),則調(diào)用awoken()將消息讀取出來。所以直到有messageQueue中有消息的時候,才會喚起,如果沒有java層沒有消息的時候,線程是會釋放掉cpu資源的;另外所有的ui操作都通過handler來發(fā)消息操作。
結(jié)論:
1.我們通過handler發(fā)送一個消息,都是通過looper放置對應(yīng)的messageQueue當(dāng)中,然后Looper.loop()會不斷地從messageQueue中獲取消息,有消息的話,就通過msg.target(實際就是handler).handlerMessage();
2.① 每個Thread只對應(yīng)一個Looper;② 每個Looper只對應(yīng)一個MessageQueue;③ 每個MessageQueue中有N個Message;④ 每個Message中最多指定一個Handler來處理事件。一個線程可以擁有多個handler,但是一個handler只能綁定一個線程。Looper是屬于某一個線程的,一個looper對應(yīng)一個MessageQueue。判斷這個handleMessage()方法在哪個線程上執(zhí)行,就看這個handler的looper對象是在哪個線程,就在這對應(yīng)的線程上執(zhí)行。
如果有什么不對的,還請指正!