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