Handler在Android基本上是无处不在,四大组件通信,我们自己写代码中,线程之间通信,都在用Handler。在面试中Handler也经常被问到的,所以今天特此记录一下。
Handler构造函数
打开Handler源码,我们可以看到Handler有以下几个构造函数:
这里的构造函数 主要可以分为两类:传递参数Looper(下面3个)的 和 不传递参数Looper(上面4个)的。先看不带Looper参数的构造函数:
public Handler() {
this(null, false);
}
@hide
public Handler(boolean async) {
this(null, async);
}
public Handler(Callback callback) {
this(callback, false);
}
@hide
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 " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
虽然这类构造函数有4个,但是有2个是@hide的,我们不能直接调用。带async 参数的 ,都是@hide的。所以系统并不希望我们调用这两个构造函数来设置异步消息。关于异步消息,后面再讲。我们平时new Handler的时候,async = false,都是同步消息。
public Handler(Looper looper) {
this(looper, null, false);
}
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
@hide
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
带有Looper参数的构造函数,也是不允许用户主动调用带async的构造函数的。
Handler.sendMessage(msg)
在Handler中sendMessage有关的方法,最终都会调用到sendMessageAtTime方法,其实uptimeMillis 就是当前消息要执行的系统时间:
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);
}
在构造Handler的时候,初始化了Looper和MessageQueue,这里最终调用了enqueueMessage方法:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
enqueueMessage方法做了几件事:
1.设置当前msg的target,这里将msg.target = this ,那么就是当前msg的target为当前Handler对象。这个target就是最后Looper中,轮询消息的时候,要执行msg.target.dispatchMessage方法。最终就回到了我们Handler的handleMessage方法中,执行我们的相关回调。
2.设置 msg 是同步还是异步 的,上面说能通过构造函数直接声明Handler处理同步消息还是异步消息。但是我们可以直接调用Message的setAsynchronous方法设置 消息是同步的还是异步的。
3.将当前消息插入消息队列中。
最后将消息插入到消息队列中,我们跟踪进入MessageQueue的enqueueMessage方法中:
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
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) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
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