1其监、首先看Handler發(fā)送一條消息到MessageQueue,最終會調(diào)用MessageQueue中的enqueueMessage(Message msg, long when)方法毁菱,我們來看一下這個方法中的核心代碼锌历,看如何將消息添加到MessageQueue中。
先上Handler消息機(jī)制流程圖
boolean enqueueMessage(Message msg, long when) {
//對消息的重新排序窗慎,通過判斷消息隊列里是否有消息以及消息的時間對比
msg.when = when;
Message p = mMessages;
//把剛進(jìn)入消息隊列的消息置位消息隊列的第一條消息
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
//根據(jù)時間排序卤材,為剛進(jìn)入隊列的消息尋找合適的位置
Message prev;
for (;;) {
prev = p;
p = p.next;
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
}
總體來看,消息入列就是根據(jù)Message的when屬性的大小進(jìn)行排序术吗,先執(zhí)行的放在隊列的前面帆精。
首先看第一種:當(dāng)Message為第一條消息,或執(zhí)行時間早的時候
然后隘蝎,我們再看襟企,如果新消息的執(zhí)行時間比隊列里面的消息,執(zhí)行時間晚的時候
2拱撵、消息的入列就說完了,再來看一下消息的出列流程 我們都知道乓旗,取出消息的邏輯是在Looper.loop()方法里面集索,里面最主要的是一個死循環(huán),早一點的版本里面用的while(true)循環(huán)
for (;;) {
//取出消息隊列的消息务荆,可能會阻塞
Message msg = queue.next(); // might block
//解析消息,分發(fā)消息
msg.target.dispatchMessage(msg);
}
這里要給大家說一下娱据,Linux的一個進(jìn)程間通信機(jī)制:管道(pipe)盅惜。
原理:在內(nèi)存中有一個特殊的文件,這個文件有兩個句柄(引用)结啼,一個是讀取句柄屈芜,一個是寫入句柄
主線程Looper從消息隊列讀取消息,當(dāng)讀完所有消息時井佑,進(jìn)入睡眠躬翁,主線程阻塞。子線程往消息隊列發(fā)送消息姆另,并且往管道文件寫數(shù)據(jù)坟乾,主線程即被喚醒,從管道文件讀取數(shù)據(jù)明吩,主線程被喚醒只是為了讀取消息殷费,當(dāng)消息讀取完畢低葫,再次睡眠仍律。
然后看消息是怎么取出來的水泉,我們看取出消息的邏輯,把關(guān)鍵代碼挑出來
Message msg = queue.next(); // might block
Message next() {
for (;;) {
Message prevMsg = null;
Message msg = mMessages;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
return msg;
}
}
示范一個簡單的出列流程
現(xiàn)在消息的入列和出列就說完了