这几个东西,总是觉得熟悉又不熟悉,而且更感觉“像风像雨又像雾”,总是迷迷糊糊的。现在就拿出来单独看一下,它们到底是什么东西,当然,仅仅是自己工作中的一个理解加上源码分析。
先总的说一下对这几个东西关系,总的理解为就是Handler发送Message到MessageQueue通过Looper轮询取出Message再交由Handler处理。
首先说Handler,Handler在代码中使用最多的就是从子线程发消息通知主线程来更新UI,这是我们用到Handler最多的情况。因为安卓更新UI只能在ActivityThread(主线程)进行更新,而耗时的处理操作又不能放在主线程操作,因为,一用户体验不好,二是容易程序ANR(Application Not Respond)程序无响应,所以耗时操作我们通常开启新的线程来处理,处理完后通过Handler发送消息,然后重写Handler的handleMessage方法来更新UI。
从上面分析来理解我们可以分析出来,Handler主要处理两件事,一是发送消息,二是处理消息。
Handler发送消息,我们通常会有两个系列的方法Send和Post,主要区别是Send直接处理消息,而Post需要将一系列“零件”组装成消息再调用Send方法来发送。
先看Send方法:
点击第一个方法,最终方法其会一层层调用不同的重载方法,最终调用:
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);
}
这个方法的作用就是将一个消息压入MessageQueue,从其名称看,它是一个消息队列,既然是“队列”,那就会队列的基本常规操作:
1、新建队列
2、元素入队,上面的enqueueMessage(…)就是元素入队方法。
3、元素出队, Message next()方法。
4、删除元素, removeMessage( )方法。
5、销毁队列
再看Post方法:
随便查看一个方法
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
看以看到其调用了sendMessageAtTime()方法,其中第一个参数需要一个Message,这个Message就是利用参数r,通过getPostMessage(r)得到的,其最终也是将一个消息压入消息队列。
分析到这里,Handler把Message压入MessageQueue的过程已经结束,但Handler还有一个功能就是处理Message,那Message又是怎么取出来,最终交由Handler处理的呢?Looper,就应该上场了,其单词本意有循环的意思,可以理解成发动机,它是整个消息轮询的动力来源。先不看这个类,先看上面的sendMessageAtTime消息入队列方法,这里面有一句MessageQueue queue = mQueue,通过代码追踪可以看到mQueue变量是通过new Handler()里的 mQueue = mLooper.mQueue;进行赋值的:
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;
}
mLooper又是通过mLooper = Looper.myLooper()赋值的,也就是消息队列是围绕Looper展开的,现在再来看Lopper.myLooper()静态方法,它是通过sThreadLocal静态变量存储的。