Message入列
判斷新創(chuàng)建Message處于隊(duì)列中的位置拇涤,并插入相應(yīng)位置
//截取自MessageQueue.enqueueMessage()方法來舉例(刪除了部分與此次無關(guān)代碼)
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
//標(biāo)記傳入的msg被使用
msg.markInUse();
msg.when = when;
//創(chuàng)建臨時(shí)變量來儲(chǔ)存消息隊(duì)列中的Message對(duì)象
Message p = mMessages;
boolean needWake;
/*
* 當(dāng)消息隊(duì)列中沒有消息
* 或傳入Message的觸發(fā)時(shí)間為0時(shí)
* 或傳入Message的觸發(fā)時(shí)間小于當(dāng)前消息隊(duì)列中的Message的觸發(fā)時(shí)間
*/
if (p == null || when == 0 || when < p.when) {
//把傳入的Message放入當(dāng)前消息隊(duì)列中的Message之前
msg.next = p;
//把當(dāng)前消息隊(duì)列中的Message對(duì)象重置為傳入的Message對(duì)象
mMessages = msg;
needWake = mBlocked;
} else {
/*
* 當(dāng)消息隊(duì)列中有消息
* 且傳入Message的觸發(fā)時(shí)間不為0時(shí)
* 且傳入Message的觸發(fā)時(shí)間大于當(dāng)前消息隊(duì)列中的Message的觸發(fā)時(shí)間
*/
needWake = mBlocked && p.target == null && msg.isAsynchronous();
//創(chuàng)建一個(gè)臨時(shí)變量
Message prev;
for (;;) {
//儲(chǔ)存臨時(shí)變量p(當(dāng)前消息隊(duì)列中的Messge)
prev = p;
//讓p指向自己在消息隊(duì)列中的下一條消息
p = p.next;
//當(dāng)p為null時(shí)六水,說明prev是當(dāng)前消息隊(duì)列中的最后一條消息
//或者傳入Message的觸發(fā)時(shí)間小于p的觸發(fā)時(shí)間時(shí)終止循環(huán)
if (p == null || when < p.when) {
break;
}
}
/* 此時(shí)的p滿足以下兩個(gè)條件中的一個(gè):
* 1.p為null時(shí),說明prev是當(dāng)前消息隊(duì)列中的最后一條消息(因?yàn)閜為null改览,所以prev不為
null且prev的觸發(fā)時(shí)間小于傳入Message的觸發(fā)時(shí)間纵刘,所以傳入Message的為消息隊(duì)列中的最
后一條消息,prev為傳入Message的上一條消息)
* 2.p的觸發(fā)時(shí)間大于傳入Message的觸發(fā)時(shí)間(因?yàn)閜的觸發(fā)時(shí)間大于傳入Message的觸發(fā)時(shí)
間振亮,所以p在消息隊(duì)列中是傳入Message的下一條消息隔躲,因?yàn)樵谏弦淮窝h(huán)中沒有進(jìn)入if語句扛稽,
所以prev不為null且觸發(fā)時(shí)間小于傳入Message對(duì)象的觸發(fā)時(shí)間浮驳,所以prev在消息隊(duì)列中處于
傳入Message的上一條)
*/
msg.next = p;
prev.next = msg;
}
}
return true;
}
Message的獲取方式
Message的獲取方式除了new Message這種方式悍汛,Message類還提供了obtain方法來獲取Message
//Message類中有一個(gè)靜態(tài)全局變量來儲(chǔ)存空閑或者回收的Message對(duì)象
private static Message sPool;
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0;
sPoolSize--;
return m;
}
}
return new Message();
}
這種方式是把靜態(tài)全局變量sPool(這里可以把這個(gè)Message看做當(dāng)前消息池中的第一條消息)標(biāo)記為未使用然后返回,如果sPool為null才會(huì)創(chuàng)建新的Message對(duì)象至会,這樣不會(huì)造成資源的浪費(fèi)离咐,避免創(chuàng)建太多Message對(duì)象。關(guān)于為什么sPool會(huì)是被回收的Message對(duì)象奉件,上源碼:
//此方法為Message的回收方法
public void recycle() {
//在回收的方法
recycleUnchecked();
};
void recycleUnchecked() {
//這里在做一些重置的工作
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
//當(dāng)消息池里消息的數(shù)量小于消息池的最大容量時(shí)
if (sPoolSize < MAX_POOL_SIZE) {
//重點(diǎn)O!县貌!
/*把當(dāng)前消息池中第一條消息(也就是sPool)置為當(dāng)前消息的下一條消息(sPool為
全局靜態(tài)變量术陶,所有Message都共用這一個(gè)sPool)*/
next = sPool;
/*把當(dāng)前消息置為消息池中第一條消息(因?yàn)樯弦徊襟E已經(jīng)把原來消息池中的第一條消息置為
了當(dāng)前消息的下一條消息,現(xiàn)在把當(dāng)前消息置為消息池中的第一條消息煤痕,所以sPool永遠(yuǎn)代表
消息池中的第一條消息)*/
sPool = this;
sPoolSize++;
}
}
}
可以看出Message在回收過程中梧宫,只要消息池的數(shù)量小于消息池的最大容量時(shí),就是把當(dāng)前Message放入消息池中摆碉。
Message在MessageQueue隊(duì)列中存在的形式
從Message入列方式我們也看出塘匣,再有新消息進(jìn)入隊(duì)列時(shí),是先判斷新消息的觸發(fā)時(shí)間巷帝,找出消息應(yīng)該插入消息隊(duì)列的位置馆铁,把這個(gè)位置的消息的next置為本條新消息,然后把新消息的next置為這個(gè)位置的消息的下一條消息锅睛。類似以下結(jié)構(gòu)(如果我理解有錯(cuò)埠巨,歡迎指出)。
![message](https://raw.githubusercontent.com/leibown/Study-Notes/master/img/message.png)
message
系列目錄: