【Android源码】Message 分析

作者: 指间沙似流年 | 来源:发表于2017-07-10 16:24 被阅读107次

    在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的时候,将自己添加到链表的表头。

    相关文章

      网友评论

        本文标题:【Android源码】Message 分析

        本文链接:https://www.haomeiwen.com/subject/qkjshxtx.html