美文网首页
面试 - handle之详谈Message(2)

面试 - handle之详谈Message(2)

作者: 未扬帆的小船 | 来源:发表于2019-11-11 15:12 被阅读0次

    面试handler系列:
    上一篇:面试 - handle使用及原理(1)

    Message的创建方式

    面试的时候如果问你Message有几种创建方式 ?

    1. Message msg = New Message()
      这种方式就不用怎么多说 直接就是创建了一个Message对象出来

    2. myHander.obtainMessage();myHandlerHandler类型的

    直接使用该方法就可以创建一个Message,看一下这源码

        public final Message obtainMessage()
        {
            return Message.obtain(this);
        }
    

    里面调用了我们要提到了第三个创建Message的方法

    1. Message.obtain():
    public static Message obtain(Handler h) {
            Message m = obtain();
            m.target = h;
    
            return m;
        }
    
       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();
        }
    

    上面的obtain()源码中,使用了一个链表结构存储Message作为一个缓存池,这样子可以避免重复创建多个实现对象。

    第二种创建方法,只是先调用第三种从缓存池中获取到Message的对象再将Handler赋值入给Message.target
    以上三种都是创建Message的方法

    Message缓存池相关

    Message的数据结构中

    public final class Message implements Parcelable {
            ......
        /*package*/ Message next;
    }
    

    这个很明显是一个链表的结构,我们来看一下

    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();
        }
    

    解析一下上面的源码:
    如果sPool这条Message的单链表不为null,取出链表头的Message,重置一下sPoolsPoolSize(记录链表的长度)减一
    如果sPoolnull则返回一个新的Message对象

    看一下添加MessagesPool的这个方法

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

    解释一下上面的源码:
    清除一些变量信息,然后判断一下链表没有没超过最大值,没有就添加到链头并将链表大小加一

        private static final int MAX_POOL_SIZE = 50;
    

    链表的最大值为50

    这个Message的细节就差不多看完了,主要是理解一下这种缓存池设计的一个思想吧,对于频繁创建的对象,我们最好是可以增加一个缓存池,需要对象的时候直接在里面获取到之前已经创建过的对象。而不是每次都是直接去创建。

    相关文章

      网友评论

          本文标题:面试 - handle之详谈Message(2)

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