-
Note that Parcelable objects here are not supported prior to
-
the {@link android.os.Build.VERSION_CODES#FROYO} release.
*/
public Object obj;
Message
的创建方式:虽然Message
有公有构造函数,但是建议使用其提供的obtain
系列函数来获取Message
对象,这种创建方式会重复利用缓存池中的对象而不是直接创建新的对象,从而避免在内存中创建太多对象,避免可能的性能问题。
/**
-
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) {
// 缓存池中存在可用对象时去缓存池获取 Message 对象。
if (sPool != null) {
// 获取缓存中的对象,并把缓存池指针后移。
Message m = sPool;
sPool = m.next;
m.next = null;
// 清除标志位
m.flags = 0; // clear in-use flag
// 更新当前缓存池大小
sPoolSize–;
return m;
}
}
// 缓存池中没有可用对象时直接创建一个新的 Message 对象。
return new Message();
}
Message
中有一系列obtain
函数用以在不同场景中获取对象,但这个是最核心的,其他函数都会在其内部调用它,有兴趣的同学可以自行查看源码,考虑到篇幅问题,这里就不再一一列举说明了。
看到这里,相信大家都会有一个疑问:obtain
函数是从缓存池中获取Message
对象,那缓存池中的对象是什么时候被添加进去的呢?既然缓存池中的对象都是一些可以被重复使用的对象,很明显是在Message
对象不再被需要的时候,即从MessageQueue
中取出并分发给Handler
的时候,被添加到缓存中的,使用的是recycleUnchecked
函数:
/**
-
Recycles a Message that may be in-use.
-
Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/
void recycleUnchecked() {
// 设置标志位为“使用中”,在从缓存中取出时会清除这个标志位。
flags = FLAG_IN_USE;
// Message 对象中的信息都不再有意义,在放入缓存池前直接清空。
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
// 缓存池中只缓存一定数量的 Message 对象,默认是 50 个。
if (sPoolSize < MAX_POOL_SIZE) {
// 把对象放在缓存池的链表首部。
next = sPool;
sPool = this;
// 及时更新缓存池大小。
sPoolSize++;
}
}
}
3.2 创建消息队列
消息队列的创建对消息传递至关重要,它决定了消息在传递过程中的存取方式。但是线程在默认情况下是没有消息队列的,也无法在其内部进行消息循环。如果想为线程开启消息循环就需要使用到Looper
类,它可以为关联的线程创建消息队列并开启消息循环,创建消息队列的方式是调用prepare()
接口:
/**
-
Class used to run a message loop for a thread. Threads by default do
-
not have a message loop associated with them; to create one, call
-
{@link #prepare} in the thread that is to run the loop, and then
-
{@link #loop} to have it process messages until the loop is stopped.
*/
public final class Looper {
// 省略无关代码
// sThreadLocal.get() will return null unless you’ve called prepare().
static final ThreadLocal sThreadLocal = new ThreadLocal();
// 内部的消息队列和关联的线程
final MessageQueue mQueue;
final Thread mThread;
// 省略无关代码
/** Initialize the current thread as a looper.
-
This gives you a chance to create handlers that then re