Principle Android Advanced Learning --Message multiplexing mechanism

In everyday Android development, we often use the Handler for message transfer between the master thread, which we use most is the Message object. After a review of official documentation or code comments we can find for Message, the official suggested that we use Message.obtain to get the Message object.

So the question is, why Google would suggest that we use Message.obtain to obtain an object rather than a new Message ourselves out of it? Or, to get the Message object by Message.obtain there any good is it?

In fact, the answers are in the source code again, and here it comes, we have to mention a design pattern - Flyweight, and this is a singleton design pattern is very similar design patterns, specific details will not talk about here the interest, then welcome to the venue and rookie tutorial - Flyweight .

Here let us start it from the source, Message multiplexing principle of entry in Message.obtain in:

/**
        从Message池中返回一个Message对象,并且允许分配新的实例
     */
    public static Message obtain() {
        //先是加了一把对象锁,这个锁是使用Object来实现的
        synchronized (sPoolSync) {
            if (sPool != null) {
                //如果Message池中非空,就从池子里取出一个Message
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        //如果Message池为空,就新建一个Message对象出来
        return new Message();
    }

Obtain the code, we can see that the first judge a Message Pool is not empty, if not empty it is used from the pool before removing Message multiplexes, and the number of asynchronously to the pool Message It has been updated. But if the pool is empty, then Message Description Message has not been put in, then out of a new Message object better.

Here, is only used before Message was taken out, or create a new Message action, have not seen the Message in the end is how to be recycled, do not worry, let us recycle method of the venue Message.

public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                throw new IllegalStateException("This message cannot be recycled because it "
                        + "is still in use.");
            }
            return;
        }
        //最终调用到了这个方法
        recycleUnchecked();
    }

    /**
     * Recycles a Message that may be in-use.
     * Used internally by the MessageQueue and Looper when disposing of queued Messages.
        这句话的意思是:一般来说这个方法是被内部的MessageQueue和Looper在分发排序的Message时候来使用的
     */
    void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        //先把这个Message标记为使用状态,防止被二次回收
        //然后把这个Message的相关状态进行了手动复位
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = -1;
        when = 0;
        target = null;
        callback = null;
        data = null;
        //Message的复用机制使用了链表数据结构来实现
        //但神奇的是这个链表没有借助任何一种数据结构如LinkedList等实现,而是通过指针的形式,将不        
        //同的Message对象进行了串联
        //在这里,先是判断了一把,如果当前Message池子的大小还没到限制值
        //那么就把当前Message池子的头指向了当前Message实例的sPool字段,也就是Message池的头        
        //部,当然,next字段和Message池子都属于Message类型
        //并且更新了池子的大小
        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }

We can see from the code, Message multiplexing mechanism does not use any data structure, such as LinkedArrayList, but, to be managed by the object pointer way through the interior of the Message object spool and the next field, I have to say yes a very clever way of design, a design to reduce complexity, and because no additional data container to create managed objects, reducing the pressure on memory, to achieve the purpose of weight reduction.

Specific implementation process I found a diagram to explain:

In the Message pond initial state, if a Message came to the pool, he must first be cleared of the data, and then his sPool field points to the head Message pool, and point to the next field empty, when the second Message is after the recovery came, m2 of the next field points to the m1, m1 the next original field remained unchanged, while the head pond Message is sPool pointed m2.

Such cycle to cycle, a Message list also completed, so as to realize multiplexing Message object.

Published 41 original articles · won praise 8 · views 20000 +

Guess you like

Origin blog.csdn.net/huma8848888/article/details/104072695