说起 Handler,都离不开 Message、MessageQueue、Looper 和 Handler 这四大件,我们知道需要重写 Handler 的 handleMessage
方法来处理 Message,Looper 让 MessageQueue 循环起来传递 Message,但是其中的过程又是怎么操作的呢?来从源码看一下吧。本文篇幅可能会很长,预警预警!
既然是消息传递,那就先看一下 Message,总所周知,Message 对象是携带数据的,我们如何得到 Message 对象呢?
// Message 构造方法
public Message() {
}
// Message 静态方法
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();
}
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;
m.sendingUid = orig.sendingUid;
if (orig.data != null) {
m.data = new Bundle(orig.data);
}
m.target = orig.target;
m.callback = orig.callback;
return m;
}
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
public static Message obtain(Handler h, Runnable callback) {
Message m = obtain();
m.target = h;
m.callback = callback;
return m;
}
public static Message obtain(Handler h, int what) {
Message m = obtain();
m.target = h;
m.what = what;
return m;
}
public static Message obtain(Handler h, int what, Object obj) {
Message m = obtain();
m.target = h;
m.what = what;
m.obj = obj;
return m;
}
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;
}
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;
}
// Handler 对象的 obtainMessage 方法
public final Message obtainMessage()
{
return Message.obtain(this);
}
public final Message obtainMessage(int what)
{
return Message.obtain(this, what);
}
public final Message obtainMessage(int what, int arg1, int arg2)
{
return Message.obtain(this, what, arg1, arg2);
}
public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
{
return Message.obtain(this, what, arg1, arg2, obj);
}
public final Message obtainMessage(int what, Object obj)
{
return Message.obtain(this, what, obj);
}
除了构造方法之外,其余的方法都会调用 obtain 方法,详细看一下这个方法:
private static final Object sPoolSync = new Object();
private static Message sPool;
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) { // 如果消息不为空,则复用该消息,而不是新建对象
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // 复用消息之前,需要先重置其标志位
sPoolSize--;
return m;
}
}
return new Message();
}
可以看到,如果 sPool 不为空,则直接返回;如果为空,则新建一个 Message 对象返回,所以 Android 建议我们使用 obtain 方法获取 Message,这样比直接新建 Message 对象要节省内存一些。
创建好 Message 之后,我们再给这个空的 Message 设置所要携带的数据和属性:
public int what; // Message 标识
public int arg1; // Message 传递整形数据
public int arg2;
public Object obj; // Message 传递 Object 类型数据
// Message 传递 Bundle 对象
public void setData(Bundle data) {
this.data = data;
}
// Message 的发送时间
这样,一个满载数据的 Message 就创建出来了。当然 Message 还有其他属性和方法,这个在后面会讲到。
一个消息创建出来了,我们需要将它发送出去,谁来发送,发送到哪里,就是 Handler 的事儿了
Handler 对象的创建有以下方法:
final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;
final boolean mAsynchronous;
public Handler() {
this(null, false);
}
public Handler(Callback callback) {
this(callback, false);
}
public Handler(Looper looper) {
this(looper, null, false);
}
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
// 下面的构造方法无法直接调用,但上面的方法最终都会调用到它
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public Handler(boolean async) {
this(null, async);
}
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
可以看到,在创建 Handler 对象的同时,也为该 Handler 初始化了一个 Looper 对象和一个 MessageQueue 对象(关于 Looper 和 MessageQueue 在下文会讲解)。
然后看一下 Handler 对象发送消息的方法,Handler 提供了 sendXXX 和 postXXX 几种方法:
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageAtFrontOfQueue(Message msg) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, 0);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtFrontOfQueue(Runnable r)
{
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
public final boolean postDelayed(Runnable r, long delayMillis)
{
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
这些方法最终都会调用到 enqueueMessage
方法:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
在这个方法中会先为 Message 设置一个 target(设置为当前 Handler 对象),然后再设置消息是否同步,最后调用 MessageQueue 的 enqueneMessage
方法将消息推入消息队列当中。
关于异步消息,可以看以下博文:
到了这里,我们将一个满载着数据的 Message 对象传送到了 MessageQueue 当中,接下来呢?看一下 MessageQueue 是如何工作的。
来看 MessageQueue 的 enqueneMessage 方法:
boolean enqueueMessage(Message msg, long when) {
// 判断传入的 Message 是否设置 target
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
// 判断传入的 Message 是否已经使用过
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
// 判断消息队列是否已经退出,如果已经退出,抛出异常,不能再给其发送消息
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle(); // 释放该消息,将消息放回到消息池当中。
return false;
}
msg.markInUse(); // 将消息表示改为使用
msg.when = when; // 设置消息执行事件
Message p = mMessages; //
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// 消息队列当中没有消息
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// 消息队列有消息。将当前消息插入到适当的位置
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// 唤醒主线程
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
Message 已经传入至 MessageQueue 当中,但是并没有循环起来啊。其实,MessageQueue 只是一个循环队列,队列是重点,循环是由 Looper 去操作的。来看 Looper 代码:
看 Looper 的 loop()
方法:
public static void loop() {
final Looper me = myLooper(); // 获取到当前线程绑定的 Looper。
// 如果 Looper 为空,则抛出异常,一般发生在子线程创建 Handler 当中,因为 UI 线程会自动创建 Looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
// 拿到 Looper 维护的 MessageQueue
final MessageQueue queue = me.mQueue;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// 进入到一个死循环当中
for (;;) {
Message msg = queue.next(); // 从消息队列当中获取消息
if (msg == null) {
return;
}
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
// 【重点】分发消息,Handler 对象的 enqueueMessage 执行时,为 Message 设置 target 为当前对象
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
// 回收消息
msg.recycleUnchecked();
}
}
来看 Handler 的 dispatchMessage 方法:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
如果我们当初创建 Handler 时候传入了 Callback
对象,则 Message 交由 Callback 对象的 handleMessage 方法处理,如果当初没有传入,则由 Handler 的 handleMessage 处理,我们创建 Handler 对象时需要重写 handleMessage 方法,然后该怎么干就怎么干喽。至此,消息循环完毕。
Looper.prepare()
来获取 Looper。Looper.loop()
去循环的拿消息。sendXXX
、postXXX
方法将消息压入到 MessageQueue 当中待 Looper 去拿取。