请先参阅 Handler机制——Handler,Message,MessagQueue,Looper
前边我们提到过Handler的getPostMessage方法
private final Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain();
m.obj = token;
m.callback = r;
return m;
}
内部是调用的是Message的obtain,Looper的loop方法中最后调用的msg的recyle方法。
整个构成了Message的一个obtain体系。可以简单理解成一个长度为10的Message链表,然后通过obtain使用,通过recyle回收。现在我们来查看源代码。
private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 10;
/**
* 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;
sPoolSize--;
return m;
}
}
return new Message();
}
/**
* Same as {@link #obtain()}, but copies the values of an existing
* message (including its target) into the new one.
* @param orig Original message to copy.
* @return A Message object from the global pool.
*/
public static Message obtain(Message orig) {
Message m = obtain();
m.what = orig.what;
m.arg1 = orig.arg1;
m.arg2 = orig.arg2;
m.obj = orig.obj;
m.replyTo = orig.replyTo;
if (orig.data != null) {
m.data = new Bundle(orig.data);
}
m.target = orig.target;
m.callback = orig.callback;
return m;
}
/**
* Same as {@link #obtain()}, but sets the value for the target member on the Message returned.
* @param h Handler to assign to the returned Message object's target member.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
/**
* Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
* the Message that is returned.
* @param h Handler to assign to the returned Message object's target member.
* @param callback Runnable that will execute when the message is handled.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h, Runnable callback) {
Message m = obtain();
m.target = h;
m.callback = callback;
return m;
}
/**
* Same as {@link #obtain()}, but sets the values for both target and
* what members on the Message.
* @param h Value to assign to the target member.
* @param what Value to assign to the what member.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h, int what) {
Message m = obtain();
m.target = h;
m.what = what;
return m;
}
/**
* Same as {@link #obtain()}, but sets the values of the target, what, and obj
* members.
* @param h The target value to set.
* @param what The what value to set.
* @param obj The object method to set.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h, int what, Object obj) {
Message m = obtain();
m.target = h;
m.what = what;
m.obj = obj;
return m;
}
/**
* Same as {@link #obtain()}, but sets the values of the target, what,
* arg1, and arg2 members.
*
* @param h The target value to set.
* @param what The what value to set.
* @param arg1 The arg1 value to set.
* @param arg2 The arg2 value to set.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h, int what, int arg1, int arg2) {
Message m = obtain();
m.target = h;
m.what = what;
m.arg1 = arg1;
m.arg2 = arg2;
return m;
}
/**
* Same as {@link #obtain()}, but sets the values of the target, what,
* arg1, arg2, and obj members.
*
* @param h The target value to set.
* @param what The what value to set.
* @param arg1 The arg1 value to set.
* @param arg2 The arg2 value to set.
* @param obj The obj value to set.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h, int what,
int arg1, int arg2, Object obj) {
Message m = obtain();
m.target = h;
m.what = what;
m.arg1 = arg1;
m.arg2 = arg2;
m.obj = obj;
return m;
}
/**
* Return a Message instance to the global pool. You MUST NOT touch
* the Message after calling this function -- it has effectively been
* freed.
*/
public void recycle() {
clearForRecycle();
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
所有的obtain有参方法最终都是调用无参的obtain。查看obtain我们发现,首先他是线程安全的,然后每次是先取sPool,如果为空就新new一个对象,如果不为空就返回sPool并把sPool指向链表的下一个元素,同时sPoolSize--。
查看recyle方法,首先调用clearForRecycle,清除msg身上的所有信息。
/*package*/ void clearForRecycle() {
flags = 0;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
when = 0;
target = null;
callback = null;
data = null;
}
然后也是线程安全的,如果sPoolSize还没有达到最大,就把当前的msg插入到sPool链表的队首,然后sPoolSize++,原理还是很简单的。
其实obtain机制就是最大限度的重复利用对象,避免new太多的msg对象。