在Handler中,我们都会通过发送Message的方式,在主线程中更新UI。那么系统是如何构建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的文档中,建议我们在构建Message的时候通过obtain来构建,通过源码我们发现了一个关键词sPool
。而通过字面意思可以理解为Message的消息对象池,但是sPool并不是Map这样的集合,那么这个对象池到底是什么呢?
// sometimes we store linked lists of these things
/*package*/ Message next;
通过注释不难发现,Message的消息池并不是一个类似Map的容器,而是使用的链表。通过next
指定下一个Message。大概意思如下:
next next next
Message -> Message -> Message -> null
这样所有的Message都通过next串联在一起。
通过obtain来获取Message,就是通过next来获取的,并且会将sPoolSize的长度减一。
但是obtain并没有添加对象到对象池中,那么sPool是如何添加Message的呢?
which will pull them from a pool of recycled objects.
通过注释发现创建的时候并没有把Message放到对象池中,而是在回收Message的时候该对象才会被放到链表中。
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++;
}
}
}
在回收的时候:
- 首先判断该消息是否还在使用,如果还在使用则抛出异常
- 清空该消息的各种字段
- 判断是否要将消息放到对象池中,当池的size小于50的时候,将自己添加到链表的表头。
网友评论