Android Message详解

一、Message定义

  Message类官方介绍如下:

 

    /**
     * User-defined message code so that the recipient can identify
     * what this message is about. Each {@link Handler} has its own name-space
     * for message codes, so you do not need to worry about yours conflicting
     * with other handlers.
     */
    public int what;

 

  定义一个包含描述和任意数据对象的消息,该对象可以发送给Handler。此对象包含两个额外的int字段和一个额外的object对象字段,可以使你在很多情况下不需要做分配工作。尽管Message的构造函数是public公开属性,然而获取一个消息类最好的方式是调用Message.obtain()方法或者是Handler.obtain()方法,它将从一个可回收对象池中获取Message对象。



二、Message成员变量

  1.what(int)
    

    /**
     * User-defined message code so that the recipient can identify
     * what this message is about. Each {@link Handler} has its own name-space
     * for message codes, so you do not need to worry about yours conflicting
     * with other handlers.
     */

    使用者自定义的消息标志符号,以便接收方可以识别这条消息是关于什么的。任何一个Handler有它自己的和消息标志符对应的名称空间,因此你不用担心和其他的Handlers发生冲突。

 

  2. arg1 arg2 (int) 

  /**
     * arg1 and arg2 are lower-cost alternatives to using
     * {@link #setData(Bundle) setData()} if you only need to store a
     * few integer values.
     */
    public int arg1;

    /**
     * arg1 and arg2 are lower-cost alternatives to using
     * {@link #setData(Bundle) setData()} if you only need to store a
     * few integer values.
     */
    public int arg2;

    如果你只需要保存几个integer类型的值,相对于使用setData()方法保存数据,使用arg1和arg2是低成本的替代品。

 

  3.obj (Object)

    /**
     * An arbitrary object to send to the recipient.  When using
     * {@link Messenger} to send the message across processes this can only
     * be non-null if it contains a Parcelable of a framework class (not one
     * implemented by the application).   For other data transfer use
     * {@link #setData}.
     *
     * <p>Note that Parcelable objects here are not supported prior to
     * the {@link android.os.Build.VERSION_CODES#FROYO} release.
     */
    public Object obj;

    一个发送给接受者的任意object对象。当使用Messenger跨进程发送消息时,如果obj包含Parcelable类(),那么它只能是非空的。对于其他数据的传递,建议使用setData()方法。请注意,在FROYO Android 2.2版本发布之前并不支持Parcelable对象。


  4.replyTo(Messenger)

    /**
     * Optional Messenger where replies to this message can be sent.  The
     * semantics of exactly how this is used are up to the sender and
     * receiver.
     */
    public Messenger replyTo;

    可选的Messenger用于当前message消息发送后的回复。具体如何使用它的含义取决于发送方和接受方。


  5.sendingUid(int)

   /**
     * Optional field indicating the uid that sent the message.  This is
     * only valid for messages posted by a {@link Messenger}; otherwise,
     * it will be -1.
     */
    public int sendingUid = -1;

    可选字段,指定发送消息的uid。该字段仅对Messenger发送的消息有效,否则将会是-1。


  6.FLAG_IN_USE = 1 << 0

/** If set message is in use.
* This flag is set when the message is enqueued and remains set while it
* is delivered and afterwards when it is recycled. The flag is only cleared
* when a new message is created or obtained since that is the only time that
* applications are allowed to modify the contents of the message.
*
* It is an error to attempt to enqueue or recycle a message that is already in use.
*/
/*package*/ static final int FLAG_IN_USE = 1 << 0;

     如果该属性被设置那么这条消息正在被使用。当消息在队列时,该标志会被设置,并且在消息被传递时和之后被回收时,该标志也会保持设置。该标志只有在新消息被created或者obtained的时候清除,因为那是应用程序允许修改消息内容的唯一时间。尝试入队和回收一个正在使用的消息是错误的。



三、获取Message对象

  /*
  *
Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}). */ public 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();
    }

    从全局池中返回一个新的Message实例。让我们在很多情况下避免分配一个新的对象。

 

    /**
     * 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。在处理队列消息时,由MessageQueue和Looper内部使用。

 

    目前为止,message的sPool是我见过最好看的链表结构的复用池,Message本身是链表结构,sPool是复用池的头节点,复用是先进后出的原则。当复用池存在头节点,将头节点取出返回使用并将计数减1,由静态变量sPoolSync提供线程锁保证message复用池的线程安全。



posted @ 2021-02-05 14:23  灰熊Grizzly  阅读(1971)  评论(0编辑  收藏  举报