【Android源码】Message 分析

在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++;
       }
   }
}

在回收的时候:

  1. 首先判断该消息是否还在使用,如果还在使用则抛出异常
  2. 清空该消息的各种字段
  3. 判断是否要将消息放到对象池中,当池的size小于50的时候,将自己添加到链表的表头。
    原文作者:指间沙似流年
    原文地址: https://www.jianshu.com/p/f00b69f6b422
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞