Message的obtain机制

请先参阅 Handler机制——Handler,Message,MessagQueue,Looper
前边我们提到过Handler的getPostMessage方法

private final Message getPostMessage(Runnable r, Object token) {
        Message m = Message.obtain();
        m.obj = token;
        m.callback = r;
        return m;
    }

内部是调用的是Message的obtain,Looper的loop方法中最后调用的msg的recyle方法。
整个构成了Message的一个obtain体系。可以简单理解成一个长度为10的Message链表,然后通过obtain使用,通过recyle回收。现在我们来查看源代码。

    private static final Object sPoolSync = new Object();
    private static Message sPool;
    private static int sPoolSize = 0;

    private static final int MAX_POOL_SIZE = 10;
    
    /**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.
     */
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

    /**
     * Same as {@link #obtain()}, but copies the values of an existing
     * message (including its target) into the new one.
     * @param orig Original message to copy.
     * @return A Message object from the global pool.
     */
    public static Message obtain(Message orig) {
        Message m = obtain();
        m.what = orig.what;
        m.arg1 = orig.arg1;
        m.arg2 = orig.arg2;
        m.obj = orig.obj;
        m.replyTo = orig.replyTo;
        if (orig.data != null) {
            m.data = new Bundle(orig.data);
        }
        m.target = orig.target;
        m.callback = orig.callback;

        return m;
    }

    /**
     * Same as {@link #obtain()}, but sets the value for the target member on the Message returned.
     * @param h  Handler to assign to the returned Message object's target member.
     * @return A Message object from the global pool.
     */
    public static Message obtain(Handler h) {
        Message m = obtain();
        m.target = h;

        return m;
    }

    /**
     * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
     * the Message that is returned.
     * @param h  Handler to assign to the returned Message object's target member.
     * @param callback Runnable that will execute when the message is handled.
     * @return A Message object from the global pool.
     */
    public static Message obtain(Handler h, Runnable callback) {
        Message m = obtain();
        m.target = h;
        m.callback = callback;

        return m;
    }

    /**
     * Same as {@link #obtain()}, but sets the values for both target and
     * what members on the Message.
     * @param h  Value to assign to the target member.
     * @param what  Value to assign to the what member.
     * @return A Message object from the global pool.
     */
    public static Message obtain(Handler h, int what) {
        Message m = obtain();
        m.target = h;
        m.what = what;

        return m;
    }

    /**
     * Same as {@link #obtain()}, but sets the values of the target, what, and obj
     * members.
     * @param h  The target value to set.
     * @param what  The what value to set.
     * @param obj  The object method to set.
     * @return  A Message object from the global pool.
     */
    public static Message obtain(Handler h, int what, Object obj) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.obj = obj;

        return m;
    }

    /**
     * Same as {@link #obtain()}, but sets the values of the target, what, 
     * arg1, and arg2 members.
     * 
     * @param h  The target value to set.
     * @param what  The what value to set.
     * @param arg1  The arg1 value to set.
     * @param arg2  The arg2 value to set.
     * @return  A Message object from the global pool.
     */
    public static Message obtain(Handler h, int what, int arg1, int arg2) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.arg1 = arg1;
        m.arg2 = arg2;

        return m;
    }

    /**
     * Same as {@link #obtain()}, but sets the values of the target, what, 
     * arg1, arg2, and obj members.
     * 
     * @param h  The target value to set.
     * @param what  The what value to set.
     * @param arg1  The arg1 value to set.
     * @param arg2  The arg2 value to set.
     * @param obj  The obj value to set.
     * @return  A Message object from the global pool.
     */
    public static Message obtain(Handler h, int what, 
            int arg1, int arg2, Object obj) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.arg1 = arg1;
        m.arg2 = arg2;
        m.obj = obj;

        return m;
    }

    /**
     * Return a Message instance to the global pool.  You MUST NOT touch
     * the Message after calling this function -- it has effectively been
     * freed.
     */
    public void recycle() {
        clearForRecycle();

        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }

所有的obtain有参方法最终都是调用无参的obtain。查看obtain我们发现,首先他是线程安全的,然后每次是先取sPool,如果为空就新new一个对象,如果不为空就返回sPool并把sPool指向链表的下一个元素,同时sPoolSize--。
查看recyle方法,首先调用clearForRecycle,清除msg身上的所有信息。

    /*package*/ void clearForRecycle() {
        flags = 0;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        when = 0;
        target = null;
        callback = null;
        data = null;
    }

然后也是线程安全的,如果sPoolSize还没有达到最大,就把当前的msg插入到sPool链表的队首,然后sPoolSize++,原理还是很简单的。
其实obtain机制就是最大限度的重复利用对象,避免new太多的msg对象。

你可能感兴趣的:(Message的obtain机制)