Android消息机制(3)- Handler和Looper
Looper
Looper主要的作用是,不断的从MessageQueue中取出Message,交给Message的target(Handler)处理。
打开Looper的源码,发现一段注释的代码:
* <pre>
* class LooperThread extends Thread {
* public Handler mHandler;
* public void run() {
* // 初始化Looper
* Looper.prepare();
* // 初始化Handler
* mHandler = new Handler() {
* public void handleMessage(Message msg) {
* // process incoming messages here
* }
* };
* // Looper不断取Message
* Looper.loop();
* }
* }</pre>
这是怎么在子线程中,正确的使用消息机制的代码。
先看看Looper.prepare();做了什么:
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
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));
}
注意 ThreadLocal ,按我自己的理解,他内部保存一个Map,Key为线程,Value是你要保存的值。使用ThreadLocal,可以保证一个线程,只有一个副本。sThreadLocal被声明为ThreadLocal,也就说明一个线程只有一个Looper。
接着我们看看Looper.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;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// 死循环,一直取消息
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
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
// 交给Handler处理消息
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
// 回收Message
msg.recycle();
}
}
public static Looper myLooper() {
return sThreadLocal.get();
}
Looper.loop()其实就是一直从MessageQueue取出消息,有就交给target(Handler)处理,没有就阻塞。代码很简单,原理也不难,但是Looper非常重要。
额外还要知道之前说过一个东西,叫“同步分割栏”,在Looper中,代码为:
// 设置同步分割栏
public int postSyncBarrier() {
return mQueue.enqueueSyncBarrier(SystemClock.uptimeMillis());
}
// 取消同步分割栏
public void removeSyncBarrier(int token) {
mQueue.removeSyncBarrier(token);
}
Handler
Handler是消息的产生者和消费者。Handler会将Message加入MessageQueue中,Looper不断地从MessageQueue中取出Message,交给target的Handler处理。
先看看Handler的构造函数,主要的有2个:
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;
}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
如果我们new一个Handler实例时,没有指定Looper的话,默认使用当前线程Looper。但是如果当前线程的Looper还没有初始化,就会报错。所以我们在示例中,要先调用Looper.prepare();初始化。mCallback是一个接口,代码:
public interface Callback {
public boolean handleMessage(Message msg);
}
再看看Handler处理消息的代码:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
// 如果mCallback不为null,消息直接交给mCallback处理
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
所以我们new一个Handler不一定要重写handleMessage(Message)方法,还可以设置mCallback来处理消息。
再从构造函数有一个mAsynchronous,这是就是设置同步/异步,暂时先不用太在意。
我们再来看看Handler怎么“发送”Message到MessageQueue,代码:
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(Runnable r, long uptimeMillis) {
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) {
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
public final boolean postDelayed(Runnable r, long delayMillis) {
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
public final boolean postAtFrontOfQueue(Runnable r) {
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
public final boolean sendMessage(Message msg) {
return sendMessageDelayed(msg, 0);
}
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);
}
从代码可以看出,postXXX和sendXXX最终都调用了sendMessageDelayed和sendMessageAtTime这两个方法。我们先看看sendMessageDelayed方法:
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
sendMessageDelayed方法最终调用了sendMessageAtTime,所以正真的大Boss是sendMessageAtTime,看看:
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);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
// 把目标设置为自己
msg.target = this;
// 设置同步/异步
if (mAsynchronous) {
msg.setAsynchronous(true);
}
// 加入到MessageQueue中
return queue.enqueueMessage(msg, uptimeMillis);
}
然后我们看看Looper取出之后,Handler处理消息的代码(其实上面已经有了):
// Looper代码片段: 取出Message,调用target的dispatchMessage方法处理消息
msg.target.dispatchMessage(msg);
// Handler的dispatchMessage方法
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
// post(Runnable)在这里处理
handleCallback(msg);
} else {
if (mCallback != null) {
// return true就不执行重写的handleMessage
if (mCallback.handleMessage(msg)) {
return;
}
}
// 我们继承Handler的子类重写的handleMessage方法
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
dispatchMessage方法内,首先看看Message的Callback有没有,那么Message的Callback什么时候才不为null呢?答案在这里:
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
当我们使用Handler.post(Runnable)时,此时Message的callback就是Runnable,这下理解了吧。虽然使用了很多次,这下终于知道原理了。
接着看dispatchMessage,之前也说了mCallback,如果mCallback没有处理,那么我们声明Handler时重写的handleMessage方法就会执行。Handler处理消息就这么简单。
上一篇: JSP简单用户管理(无javabean)
推荐阅读
-
Android消息处理机制Looper和Handler详解
-
Android Studio 之 Android消息机制 之简单Demo --- 使用Handler和Message类来完成消息传递
-
Android技术点记录-handler消息传递机制
-
Android消息机制(3)- Handler和Looper
-
Handler异步消息传递机制(四)Handler发送消息流程,源码(Android 9.0)彻底解析
-
Android Handler 机制 - Looper,Message,MessageQueue
-
Android消息通信机制Handler详解,Handler,Looper,MessageQueue,源码解析,讲解这几个类怎么配合工作的
-
Android Handler消息机制实现原理
-
Android消息处理机制(Handler、Looper、MessageQueue与Message)
-
Android异步消息处理机制 深入理解Looper、Handler、Message的关系