我們知道Android提供了Handler 和 Looper 來(lái)滿足線程間的通信,之前通過(guò)Handler和Looper的學(xué)習(xí)帮掉,知道
1、子線程通過(guò)Handler對(duì)象來(lái)與Looper(一個(gè)線程可以產(chǎn)生一個(gè)Looper對(duì)象)溝通窒典,
2蟆炊、push新消息到MessageQueue里;或者接收Looper從Message Queue取出)所送來(lái)的消息。
3瀑志、將消息放到Looper的MessageQueue中涩搓。
4污秆、Looper收到消息后就開(kāi)始處理了,
5昧甘、由Looper交由Handler處理良拼,Handler最終將消息發(fā)送給主線程。
那么我們今天就來(lái)講講MessageQueue充边!
一:變量
//mQuitAllowed表示MessageQueue是否允許退出庸推,系統(tǒng)創(chuàng)建的UI線程的MessageQueue是不允許的,其他客戶端代碼創(chuàng)建的都是允許的浇冰;
private final boolean mQuitAllowed;
//mPtr是native代碼相關(guān)的贬媒,指向C/C++代碼中的某些對(duì)象(指針)
private long mPtr; // used by native code
//mMessages表示消息隊(duì)列的頭Head;
Message mMessages;
//mIdleHandlers是IdldHandler接口的ArrayList, mPendingIdleHandlers是數(shù)組版本肘习,在后面的代碼中會(huì)將ArrayList的內(nèi)容拷貝到它里面际乘;
private final ArrayList mIdleHandlers = new ArrayList();
//IdleHandler接口表示當(dāng)MessageQueue發(fā)現(xiàn)當(dāng)前沒(méi)有更多消息可以處理的時(shí)候則順便干點(diǎn)別的事情的callback函數(shù)
private IdleHandler[] mPendingIdleHandlers;
//表示當(dāng)前隊(duì)列是否處于正在退出狀態(tài);
private boolean mQuitting;
// Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout.
//mBlocked表示next()調(diào)用是否被block在timeout不為0的pollOnce上井厌;
private boolean mBlocked;
//mNextBarrierToken表示下一個(gè)barrier token蚓庭,barrier用target==null, arg1==token的Message對(duì)象表示;
private int mNextBarrierToken;
//注:ctor中初始化mQuitAllowd和native的mPtr指針仅仆;
二器赞、方法
MessageQueue作為Message存儲(chǔ)的一個(gè)單鏈表,重要的是兩個(gè)方法墓拜,enqueueMessage和next港柜。enqueueMessage其主要操作是向MessageQueue單鏈表中插入數(shù)據(jù)。主要看一下next方法咳榜。
通過(guò)代碼片段:
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
夏醉、、涌韩、
msg.next = null;
if (false) Log.v("MessageQueue", "Returning message: " + msg);
return msg;
}
可以發(fā)現(xiàn)next是是一個(gè)無(wú)限循環(huán)的方法畔柔,唯一跳出循環(huán)的條件是取出MessageQueue中的msg,然后return msg (同時(shí)將Message從MessageQueue中移除)。如果MessageQueue 中沒(méi)有消息臣樱,那么next方法將一直阻塞在這里靶擦,只有執(zhí)行Loop.quit/quitSafely才會(huì)跳出循環(huán)。如果MessageQueue中有Message則執(zhí)行msg.target.dispatchMessage(msg)雇毫。
那么問(wèn)題來(lái)了玄捕。。
這里死循環(huán)了棚放,那Activity怎么響應(yīng)onCreate或者按鈕的點(diǎn)擊事件呢枚粘?
Activity內(nèi)部真正運(yùn)行的是ActivityThread,ActivityThread的內(nèi)部類H繼承于Handler飘蚯,通過(guò)handler消息機(jī)制馍迄,簡(jiǎn)單說(shuō)Handler機(jī)制用于同一個(gè)進(jìn)程的線程間通信福也。Activity的生命周期都是依靠主線程的Looper.loop,當(dāng)收到不同Message時(shí)則采用相應(yīng)措施:在H.handleMessage(msg)方法中攀圈,根據(jù)接收到不同的msg拟杉,執(zhí)行相應(yīng)的生命周期。也就是說(shuō)這個(gè)死循環(huán)是為了給Activity處于一種時(shí)刻運(yùn)行狀態(tài)的機(jī)制量承。
最后引申一下:
從進(jìn)程與線程間通信的角度,通過(guò)一張圖加深大家對(duì)App運(yùn)行過(guò)程的理解:
結(jié)合圖說(shuō)說(shuō)Activity生命周期穴店,比如暫停Activity撕捍,流程如下:線程1的AMS中調(diào)用線程2的ATP;(由于同一個(gè)進(jìn)程的線程間資源共享泣洞,可以相互直接調(diào)用忧风,但需要注意多線程并發(fā)問(wèn)題)線程2通過(guò)binder傳輸?shù)紸pp進(jìn)程的線程4;線程4通過(guò)handler消息機(jī)制球凰,將暫停Activity的消息發(fā)送給主線程狮腿;主線程在looper.loop()中循環(huán)遍歷消息,當(dāng)收到暫停Activity的消息時(shí)呕诉,便將消息分發(fā)給ActivityThread.H.handleMessage()方法缘厢,再經(jīng)過(guò)方法的調(diào)用,最后便會(huì)調(diào)用到Activity.onPause()甩挫,當(dāng)onPause()處理完后贴硫,繼續(xù)循環(huán)loop下去。
引申內(nèi)容的作者:Gityuan