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