其实网上已经有很多写的很好很优秀的文章了,我这里就是想写一篇来捋清思路,同时加深记忆。
这里推荐一篇优秀的文章:
https://blog.csdn.net/zip_tts/article/details/86097136#commentBox
Handler消息机制主要还是有5个组件,Handler、Looper、Message、MessageQueue、ThreadLocal
- Handler作为消息处理中心,用于处理消息和发送消息。
- Looper作为消息传送的动力,用于获取分发消息。
- Message作为消息载体,用于承载消息。
- MessageQueue作为消息队列,用于存放消息。
- ThreadLocal是一个线程内部的数据存储类,只有在指定线程中才可以获得数据。
**
一、Message是什么
首先还是要明白,我们要传输的Message是什么,里面有什么东西。
public final class Message implements Parcelable {
public int what;
public int arg1;
public int arg2;
public Object obj;
public Messenger replyTo;
int flags;
long when;
Bundle data;
Handler target;
}
是不是都觉得挺熟悉的?好多都是我们写方法需要用到的。
这里介绍一个 target,是Handler类型的,即存放该Message是哪个Handler的Message,这对我们理解后面部分有帮助。
二、Handler实例化及发送信息
实例化handler有7个构造方法
public Handler() {
this(null, false);
}
public Handler(Callback callback) {
this(callback, false);
}
public Handler(Looper looper) {
this(looper, null, false);
}
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
public Handler(boolean async) {
this(null, async);
}
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;
}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
从代码中可以看到,如果没有指定Looper,则使用实例化Handler时所在线程的Looper。
关于Handler的发送,其实有不少方法,但是观察一下就能发现,最终的方法都是指向enqueueMessage,且都是将消息封装在Message中,然后发送出去。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
以上代码,将该Message的target指向自己,发送到MessageQueue中,很好理解,下面来分析MessageQueue的enququqMessage()
三、MessageQueue
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 {
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
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
其实就是消息队列,有消息了就按时间存储在链表中,如果没有设置延迟就按顺序,有就按时间排序。
四、Looper
下面是Looper的构造函数:
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
可以看到,它的构造方法是private,即Looper是不能通过new方法创建对象的,那么它肯定会有其他方法可以得到。继续查看源码发现,它的内部还有prepareMainLooper,prepare方法,
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
prepareMainLooper主要还是用于创建主线程的Looper,一般情况下,是禁止使用的,因为主线程的Looper总是存在。并且可以看到,创建的主要方法还是prepare()。
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));
}
这里的ThreadLocal即
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
很显然,这样该线程的Looper就创建出来,并且存到ThreadLocal中了。
那么现在Looper已经创建出来,如何运用它,把Message发送到MessageQueue中呢?那就是Loop()
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
try {
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
}
删去了些代码,上面差不多是核心代码。MessageQueue本质上就是一个单链表,Loop用的是for(;; ),是一个死循环,不停通过next获取MessageQueue的Message,如果为空就直接return,否则通过msg.target.dispatchMessage(msg)
将信息发送到msg.target这个handler类型的dispatchMessage中去。
五、handler的获取和处理
那么代码就来到了handler中的dispatchMessage()中
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
这里有一些判断语句。在Handler中,声明了一个接口Callback,里面只有一个方法handleMessage,这个方法就是处理Message消息的,Callback在构造方法中传入。当然,若是在构造方法中没有传入Callback的话还有一种方式,Handler中也定义了一个handleMessage方法,默认是个空实现。可以通过重写这个方法来处理Message消息。
那么这一整套流程就结束啦。