Message是具体的消息携带者
MessageQueue用来存储Message
Looper开启一个循环从MessageQueue中获取数据并将数据分发给当前线程进行处理
Handler主要用来向MessageQueue中添加数据,同时也处理Looper分发过来的数据
Android中的消息机制,我们主要用来处理子线程和主线程之间的通信,但不是只能处理子线程跟主线程的通信,它也可以处理两个子线程之间的通信。取决于Handler创建时传入的Looper,Handler无参的构造函数是直接获取当前线程的Looper源码如下:
public Handler(@Nullable 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;
}
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
Looper与当前线程的关系是一个线程只能有一个Looper存在,Looper与MessageQueue的关系是一个Looper只能有一个MessageQueue存在。
Android 中Looper是不能直接通过new来直接创建的,需要调用Looper.prepare()来实现Looper的创建,而在Looper中有个静态变量sThreadLocal用来存储当前线程的具体实例来达到一个线程只有一个Looper的目的,具体源码如下:
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
MessageQueue只有一个是因为在Looper中定义了final类型的MessageQueue变量,在Looper初始化的时候调用了MessageQueue的赋值。
@UnsupportedAppUsage
final MessageQueue mQueue;
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
我们主要来说一下Handler,如下是Android官方对Handler的解释
A Handler allows you to send and process {@link Message} and Runnable
objects associated with a thread's {@link MessageQueue}. Each Handler
instance is associated with a single thread and that thread's message
queue. When you create a new Handler, it is bound to the thread /
message queue of the thread that is creating it -- from that point on,
it will deliver messages and runnables to that message queue and execute
them as they come out of the message queue.
<p>There are two main uses for a Handler: (1) to schedule messages and
runnables to be executed at some point in the future; and (2) to enqueue
an action to be performed on a different thread than your own.
就是说它有两个作用
- 调度Message和Runnable在未来某一时刻执行
- 将不同线程上执行的操作添加到队列里
Handler send系列的发送Message的方法如下:
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 sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(@NonNull 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);
}
我们发现前几个方法最后都是调用的sendMessageAtTime(@NonNull Message msg, long uptimeMillis)这个方法。
post系列的方法如下:
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
......
我们发现post系列的方法与send系列不同的是 post为Message添加了Runnable,那么这个Runnable是做什么用的呢?
我们通过查阅源码发现handler在处理消息的分发的时候有对msg.callback的判读,一起看一下源码:
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
也就是说post系列方法直接设置了回调,我们可以直接在Runnable中进行自己的处理,而send系列的方法只能在handler的callback或者 重写的handlerMessage方法中处理自己的操作。