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.
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方法中处理自己的操作。