(M)Android消息处理机制分析之Message类解析

来源:互联网 发布:美工设计班 编辑:程序博客网 时间:2024/06/16 09:21

首先,我们查看一下Google 对于 Message类的备注

/** *  * Defines a message containing a description and arbitrary data object that can be * sent to a {@link Handler}.  This object contains two extra int fields and an * extra object field that allow you to not do allocations in many cases.   * * <p class="note">While the constructor of Message is public, the best way to get * one of these is to call {@link #obtain Message.obtain()} or one of the * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull * them from a pool of recycled objects.</p> */public final class Message implements Parcelable {......}
意思是,定义一个包含一个描述和任何类型数据的消息,可以被发送到Handler。这个任意类型数据包括了两个额外int型数据和一个额外的Object类型的数据,以便我们在许多情况下不需要分配空间。尽管Message的构造函数是public的,最好的方式还是通过调用Message的obtain方法或者Handler的obtainMessage方法来定义一个Message,这是因为这样会从一个再循环的(消息)池中取出它们。(只是自己的翻译,也许翻译不准确)

既然如此,我们就先看看Message的obtain方法中究竟做了什么?

/**     * 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;                m.flags = 0; // clear in-use flag                sPoolSize--;                return m;            }        }        return new Message();    }
sPool是一个Message对象,当sPool不为null的时候,就会直接返回sPool的对象,而不重新申请空间,而当sPool为null的时候,我们才会通过new的方式,向系统申请空间,因此,调用obtain方法的时候,会节约很多空间

/**     * 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;        m.sendingUid = orig.sendingUid;        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 <em>target</em> member on the Message returned.     * @param h  Handler to assign to the returned Message object's <em>target</em> 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 <em>target</em> 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 <em>target</em> and     * <em>what</em> members on the Message.     * @param h  Value to assign to the <em>target</em> member.     * @param what  Value to assign to the <em>what</em> 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 <em>target</em>, <em>what</em>, and <em>obj</em>     * members.     * @param h  The <em>target</em> value to set.     * @param what  The <em>what</em> value to set.     * @param obj  The <em>object</em> 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 <em>target</em>, <em>what</em>,      * <em>arg1</em>, and <em>arg2</em> members.     *      * @param h  The <em>target</em> value to set.     * @param what  The <em>what</em> value to set.     * @param arg1  The <em>arg1</em> value to set.     * @param arg2  The <em>arg2</em> 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 <em>target</em>, <em>what</em>,      * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.     *      * @param h  The <em>target</em> value to set.     * @param what  The <em>what</em> value to set.     * @param arg1  The <em>arg1</em> value to set.     * @param arg2  The <em>arg2</em> value to set.     * @param obj  The <em>obj</em> 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;    }
Message中提供了很多obtain方法,方便用户在创建Message的时候调用。

/**     * Return a Message instance to the global pool.     * <p>     * You MUST NOT touch the Message after calling this function because it has     * effectively been freed.  It is an error to recycle a message that is currently     * enqueued or that is in the process of being delivered to a Handler.     * </p>     */    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.     */    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++;            }        }    }
从方法名称上来看,这两个方法应该是回收Message,但是在这个类中,没有被回收,直接将flags职位FLAG_IN_USE,这就为obtain方法提供了可能。

/**     * Make this message like o.  Performs a shallow copy of the data field.     * Does not copy the linked list fields, nor the timestamp or     * target/callback of the original message.     */    public void copyFrom(Message o) {        this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM;        this.what = o.what;        this.arg1 = o.arg1;        this.arg2 = o.arg2;        this.obj = o.obj;        this.replyTo = o.replyTo;        this.sendingUid = o.sendingUid;        if (o.data != null) {            this.data = (Bundle) o.data.clone();        } else {            this.data = null;        }    }
从其他Message中拷贝一份一样的消息数据

public void setTarget(Handler target) {        this.target = target;    }
/**     * Retrieve the a {@link android.os.Handler Handler} implementation that     * will receive this message. The object must implement     * {@link android.os.Handler#handleMessage(android.os.Message)     * Handler.handleMessage()}. Each Handler has its own name-space for     * message codes, so you do not need to     * worry about yours conflicting with other handlers.     */    public Handler getTarget() {        return target;    }
需要注意,Message对象中的target是Handler对象

/**     * Retrieve callback object that will execute when this message is handled.     * This object must implement Runnable. This is called by     * the <em>target</em> {@link Handler} that is receiving this Message to     * dispatch it.  If     * not set, the message will be dispatched to the receiving Handler's     * {@link Handler#handleMessage(Message Handler.handleMessage())}.     */    public Runnable getCallback() {        return callback;    }
这个类中的callback是Runnable对象

/**     * Sends this Message to the Handler specified by {@link #getTarget}.     * Throws a null pointer exception if this field has not been set.     */    public void sendToTarget() {        target.sendMessage(this);    }
这个方法是我们常用的,但是需要注意,调用这个方法的时候,一定要先设定其的target参数

/**     * Returns true if the message is asynchronous, meaning that it is not     * subject to {@link Looper} synchronization barriers.     *     * @return True if the message is asynchronous.     *     * @see #setAsynchronous(boolean)     */    public boolean isAsynchronous() {        return (flags & FLAG_ASYNCHRONOUS) != 0;    }
消息是否是异步

/**     * Sets whether the message is asynchronous, meaning that it is not     * subject to {@link Looper} synchronization barriers.     * <p>     * Certain operations, such as view invalidation, may introduce synchronization     * barriers into the {@link Looper}'s message queue to prevent subsequent messages     * from being delivered until some condition is met.  In the case of view invalidation,     * messages which are posted after a call to {@link android.view.View#invalidate}     * are suspended by means of a synchronization barrier until the next frame is     * ready to be drawn.  The synchronization barrier ensures that the invalidation     * request is completely handled before resuming.     * </p><p>     * Asynchronous messages are exempt from synchronization barriers.  They typically     * represent interrupts, input events, and other signals that must be handled independently     * even while other work has been suspended.     * </p><p>     * Note that asynchronous messages may be delivered out of order with respect to     * synchronous messages although they are always delivered in order among themselves.     * If the relative order of these messages matters then they probably should not be     * asynchronous in the first place.  Use with caution.     * </p>     *     * @param async True if the message is asynchronous.     *     * @see #isAsynchronous()     */    public void setAsynchronous(boolean async) {        if (async) {            flags |= FLAG_ASYNCHRONOUS;        } else {            flags &= ~FLAG_ASYNCHRONOUS;        }    }
设置消息是否为异步

/*package*/ boolean isInUse() {        return ((flags & FLAG_IN_USE) == FLAG_IN_USE);    }
是否正在使用

/*package*/ void markInUse() {        flags |= FLAG_IN_USE;    }
设置为正在使用中

public void writeToParcel(Parcel dest, int flags) {        if (callback != null) {            throw new RuntimeException(                "Can't marshal callbacks across processes.");        }        dest.writeInt(what);        dest.writeInt(arg1);        dest.writeInt(arg2);        if (obj != null) {            try {                Parcelable p = (Parcelable)obj;                dest.writeInt(1);                dest.writeParcelable(p, flags);            } catch (ClassCastException e) {                throw new RuntimeException(                    "Can't marshal non-Parcelable objects across processes.");            }        } else {            dest.writeInt(0);        }        dest.writeLong(when);        dest.writeBundle(data);        Messenger.writeMessengerOrNullToParcel(replyTo, dest);        dest.writeInt(sendingUid);    }
打包

public static final Parcelable.Creator<Message> CREATOR            = new Parcelable.Creator<Message>() {        public Message createFromParcel(Parcel source) {            Message msg = Message.obtain();            msg.readFromParcel(source);            return msg;        }                public Message[] newArray(int size) {            return new Message[size];        }    };
实现Parcelable接口,定义CREATOR

0 0
原创粉丝点击