在Handler中,我們都會(huì)通過(guò)發(fā)送Message的方式,在主線程中更新UI。那么系統(tǒng)是如何構(gòu)建Message的,Message又是如何操作的?
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
在Message的文檔中,建議我們?cè)跇?gòu)建Message的時(shí)候通過(guò)obtain來(lái)構(gòu)建,通過(guò)源碼我們發(fā)現(xiàn)了一個(gè)關(guān)鍵詞sPool。而通過(guò)字面意思可以理解為Message的消息對(duì)象池,但是sPool并不是Map這樣的集合,那么這個(gè)對(duì)象池到底是什么呢?
// sometimes we store linked lists of these things
/*package*/ Message next;
通過(guò)注釋不難發(fā)現(xiàn),Message的消息池并不是一個(gè)類似Map的容器,而是使用的鏈表。通過(guò)next指定下一個(gè)Message。大概意思如下:
next next next
Message -> Message -> Message -> null
這樣所有的Message都通過(guò)next串聯(lián)在一起。
通過(guò)obtain來(lái)獲取Message,就是通過(guò)next來(lái)獲取的,并且會(huì)將sPoolSize的長(zhǎng)度減一。
但是obtain并沒(méi)有添加對(duì)象到對(duì)象池中,那么sPool是如何添加Message的呢?
which will pull them from a pool of recycled objects.
通過(guò)注釋發(fā)現(xiàn)創(chuàng)建的時(shí)候并沒(méi)有把Message放到對(duì)象池中,而是在回收Message的時(shí)候該對(duì)象才會(huì)被放到鏈表中。
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
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) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
在回收的時(shí)候:
- 首先判斷該消息是否還在使用,如果還在使用則拋出異常
- 清空該消息的各種字段
- 判斷是否要將消息放到對(duì)象池中,當(dāng)池的size小于50的時(shí)候,將自己添加到鏈表的表頭。