Message解析
1 数据成员
public int what; //用户自定义消息码,每个Handler都有自己的命名空间,所以无需担心和其它Handler发生冲突
public int arg1; //当仅仅需要存贮少量的整数值的时候arg1可以用来替代setData()函数,它优点是消耗低,效率高
public int arg2; //当仅仅需要存贮少量的整数值的时候arg2可以用来替代setData()函数,它优点是消耗低,效率高
public Object obj; //传递给接受者的任意对象。当用Messenger在进程间传递消息的时候,如果它包含了一个框架类的
//Parcelable实现(而不是由应用程序实现的),那么这个对象只能是非空的。
public Messenger replyTo; //暂时不理解
public int sendingUid = -1;
static final int FLAG_IN_USE = 1 << 0;
static final int FLAG_ASYNCHRONOUS = 1 << 1;
static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
int flags;
long when;
Bundle data;
Handler target;
Runnable callback;
Message next;
private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
private static boolean gCheckRecycle = true;
2 重要成员函数分析
2.1
这个函数的好处是当sPool不是null的时候,可以将sPool作为消息的实例,从而避免了重现开辟空间的开销,但是当sPool为空
的时候还是要调用Message的构造函数的。
2.2
这个函数在这里完成了一件事情,就是给sPool赋值,这样就把消息回收到了消息池子中,并且消息池子的最大长度是MAX_POOL_SIZE。
所以很明显sPool是一个有长度限制的链表。
这个函数调用了上面的recycleUnchecked()函数,因为在recycleUnchecked函数中,Message被有效的释放,所以在这个函数被调用后,
不能立即处理这个消息。
3 Message的源码
1 数据成员
public int what; //用户自定义消息码,每个Handler都有自己的命名空间,所以无需担心和其它Handler发生冲突
public int arg1; //当仅仅需要存贮少量的整数值的时候arg1可以用来替代setData()函数,它优点是消耗低,效率高
public int arg2; //当仅仅需要存贮少量的整数值的时候arg2可以用来替代setData()函数,它优点是消耗低,效率高
public Object obj; //传递给接受者的任意对象。当用Messenger在进程间传递消息的时候,如果它包含了一个框架类的
//Parcelable实现(而不是由应用程序实现的),那么这个对象只能是非空的。
public Messenger replyTo; //暂时不理解
public int sendingUid = -1;
static final int FLAG_IN_USE = 1 << 0;
static final int FLAG_ASYNCHRONOUS = 1 << 1;
static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
int flags;
long when;
Bundle data;
Handler target;
Runnable callback;
Message next;
private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
private static boolean gCheckRecycle = true;
2 重要成员函数分析
2.1
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不是null的时候,可以将sPool作为消息的实例,从而避免了重现开辟空间的开销,但是当sPool为空
的时候还是要调用Message的构造函数的。
2.2
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++;
}
}
}
这个函数在这里完成了一件事情,就是给sPool赋值,这样就把消息回收到了消息池子中,并且消息池子的最大长度是MAX_POOL_SIZE。
所以很明显sPool是一个有长度限制的链表。
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
这个函数调用了上面的recycleUnchecked()函数,因为在recycleUnchecked函数中,Message被有效的释放,所以在这个函数被调用后,
不能立即处理这个消息。
3 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 {
/**
* User-defined message code so that the recipient can identify
* what this message is about. Each {@link Handler} has