Handler主要作用:
1、 向线程的消息队列MessageQueue中添加Message;
2、 处理Message消息。
为了实现上面两个操作过程,面临两个问题:Handler如何向线程的MessageQueue添加Message?线程取出消息怎么能够调用到Handler的消息处理?
针对第一个问题,Handler如何向MessageQueue添加Message,查看Handler源码可以看到Handler具有MessageQueue类型变量mQueue。
final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
final boolean mAsynchronous;
IMessenger mMessenger;
然后分析一下mQueue是如何赋值的,mQueue是final类型,Handler初始化时刻就需要赋值,查看Handler构造函数:
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的mQueue是Looper的成员变量mQueue赋值,我们看一下Looper的源码。
public final class Looper {
private static final String TAG = "Looper";
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class
final MessageQueue mQueue;
final Thread mThread;
... ...
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
}
从代码中可以看到mQueue是Looper的final成员变量,在构造的时候就会new 出一个MessageQueue对象。那么Handler的mLooper是如何赋值的?我们从Handler的构造函数中可以看到,mLooper有两种获取方式,一种是Looper.myLooper(),另一种是外部赋值。我们看一下Looper.myLooper()函数实现。
public static Looper myLooper() {
return sThreadLocal.get();
}
myLooper()是一个静态函数,从sTheadLocal中获取,sTheadLocal定义如下:
static final ThreadLocal<Looper> sThreadLocal= new ThreadLocal<Looper>();
sTheadLocal是一个静态ThreadLocal对象,ThreadLocal是怎么保存Looper对象?下面我们看一下ThreadLocal的实现。
public class ThreadLocal<T>
{
Values initializeValues(Thread current) { return current.localValues = new Values(); }
Values values(Thread current) { return current.localValues; }
static class Values
{
private Object[] table;
…
}
…
}
从上面实现我们可以看到ThreadLocal.Values是与线程相关的,存储的是线程的本地变量。根据ThreadLocal的get函数实现可知:首先获取当前Thread对象的保存的Values类型变量localValues,如果localValues为空会调用initializeValues函数为当前线程创建一个Values对象;然后从localValues中获取Looper对象。如果是非UI线程,没有调用Looper.prepare(),获取的Looper对象为空。Looper的prepare函数会new一个Looper对象放入当前线程对应的ThreadLocal.Values中。三者关系如下图
总结以上分析得出结论:
(1)使用Handler必须依赖一个Looper;
(2)Handler发送Message实际是添加到Looper的MessageQueue中;
(3)非UI线程默认是没有Looper和MessageQueue,需要调用prepare()函数;
回到开始提出的问题,Handler如何向MessageQueue添加Message,现在我们知道了MessageQueue的由来,下面看一下Handler添加Message过程。
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
我们可以向Handler传递一个Runnable对象,或者一个Message对象。当传递Runnable对象时,会把Runnable填充到一个Message对象中。
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
sendMessageDelayed函数最终会调用到enqueueMessage函数。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
这时会就把Message添加到了MessageQueue中。在enqueueMessage函数中会使用设置当前Message的target为当前的Handler对象。这时就完成了Handler的Message发送。
第二个问题:线程取出消息怎么能够调用到Handler的消息处理?
下面我们看一下Message类实现,Message对象包括两个重要成员变量,如下:
Handler target;
Runnable callback;
每个Message对象都会携带者Handler信息,这个Handler有什么作用呢?我们看一下Looper取出Message的处理过程。
Looper从MessageQueue中取出一个Message,然后调用msg的Handler对象target的dispatchMessage函数处理消息。
首先会判断msg是否有Runnable对象(msg.callback是否为空),例如前面介绍使用Handler的post一个Runnable对象时会把Runnable转为一个Message对象, Runnable对象同时赋值给Message的callback。如果msg.callback为空时会判断Handler是否设置了Callback,如果mCallback为空就会调用到handlerMessage。
Handler的消息发送和处理过程图如下: