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復用池的線程安全。




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM