Handler 是什么
Handler 的用途(主要的两个用途)
1、线程间的调度。主要有 sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long),sendMessageDelayed(Message, long) 这些方法发送消息,并通过 Handler 中的 handlerMessage() 方法接受处理返回过来的消息。
2、延时处理消息或者执行某些操作。主要有 post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long)这些方法。
Handler 相关的类
Message:消息类,包含一个描述和任意数据对象,用于 Handler 发送和接受。虽然Message 的构造函数是 public,但是一般是使用 Message.obtain() 或者 Handler.obtainMessage() 来获取 Message 实例。
MessageQueue: 消息集合,用于 Looper 分发的一个 low_level 类。
Looper:被用于消息循环线程的类。死循环从 MessageQueue 中取 Message。
ThreadLoacl:用于保存和提供线程级别的变量,主要是用来将 Looper 绑定到相关的线程上的。
Handler 工作流程

Handle 的初始化
一般情况下我们回去创建一个类继承 Hanlder 并实现其中的 handleMessage 来接收处理消息
class MyHandler extends Handler{
public MyHandler(Looper looper){
super(looper)
}
@Override
public void handleMessage(Message msg) {
//接受处理消息
}
}
然后创建 MyHandler 的实例并通过其发送消息
MyHandler myHandler = new MyHandler(looper);
......
Message message = Message.obtain();
//初始化message
......
myHanlder.sendMessage(message);
在主线程中创建 Handler 实例可以直接通过Handler hander = new Handler()
来实现,因为主线程中已经存在 Looper, Hanlder 内部可以通过 Looper.myLooper()来拿到 Looper的实例。
Handler 的构造函数最终会分为两种:
1、有 Looper 参数的情况:
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
2、没有 Looper 参数的情况:
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 为 null 创建 Handler是会失败的
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;
}
通过 Handler 的构造器可以知道,Handler 中的 MessageQueue 的实例 mQueue 是通过 Looper 拿到的。还有一个 Looper.myLooper() 的方法,后面说。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
通过 Looper 的构造器可以知道 MessageQueue 的实例是由 Loop而创建。
消息的发送
从 Handler 的定义可以知道,Handle 可以发送 Message 和 Runnable 对象到消息队列。从 Handler 源码可以跟到发送 Message 会调用下面方法:
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);
}
然后调用了 enqueueMessage 方法:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//这里把当前 Handler 实例赋给了 Message 的 target 变量,用于后期的消息分发
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
这里回去调用 MessageQueue 的 enqueueMessage方法:
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 {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
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;
}
至此 由 Handler 发送的消息已经加到 MessageQueue 当中。那么由 Handler 发送 Runnable 对象是怎样的?Handler 中的 postDelayed 的的代码:
public final boolean postDelayed(Runnable r, long delayMillis){
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
由此可知采用的是和发送消息一样的流程。Handler 会通过 * getPostMessage* 方法提供一个 Message 对象:
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
//这里把 Runnable 对象赋给了 Message 中的 callback 变量,后面的消息分发会用
m.callback = r;
return m;
}
消息的循环
消息分发是通过 Looper 实现的,所以先说下一下 Looper 这个类:
Looper 的构造函数是私有的,所以我们只能通过 Looper.myLooper() 来获取当前线程的 Looper 实例:
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
方法中并没有去 new 一个 Looper 实例,而是通过 sThreadLocal 去 get。这里的 sThreadLocal 是 ThreadLocal 的一个实例。get 方法:
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
这里会先去获取当前的线程,然后通过当前线程去拿 ThreadLocalMap 的实例(ThreadLocalMap 就是个 Map,通过Key-Value存取值)。这个map实例是在 Thread 中的,但在 Thread 中并没有初始化,初始化是在 ThreadLocal 中进行的。如果 map 为空,回去进行初始化的操作,在初始化过程中回去 new 一个 ThreadLocalMap 的实例赋给 Thread 中的 ThreadLocalMap 变量。 如果返回的值为 null 的话,说明 Looper 还没有初始化。 使用 Looper.prepare() 对 Looper进行初始化:
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));
}
初始化回去创建一个 Looper 对象并且 set 到 sThreadLocal 中去,这样 sThreadLocal 就会保留这个 Looper 对象。
关于 ThreadLocal ,主要是用来将 Looper 绑定到相关的线程上的。在 Android 系统中主线程是非安全线程,如果 Looper 没有绑定到主线程中(其他线程不能修改UI)是会抛出异常的。
消息分发是通过 Looper 的 loop 方法进行的,可以通过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
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
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);
}
msg.recycleUnchecked();
}
}
通过 MessageQueue 的 next() 或获取 Message:
Message next() {
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (false) Log.v("MessageQueue", "Returning message: " + msg);
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf("MessageQueue", "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}
在这个方法中也是采用死循环去取队列中的消息的,这里使用的是 Native 方法获取消息,涉及到的是 Linux 的的一些阻塞机制(不懂)
获取到的 Message 对象通过 Message 的 target 来分发消息,这里的 target 就是发送该 Message 实例的 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 如果发送的是 Runnable 对象,会存到 msg.callback 中,如果 Runnable 不为空,就是执行 handleCallback:
private static void handleCallback(Message message) {
message.callback.run();
}
即执行 Runnable 中的 run 方法。
如果发送的是 Message 对象,那么最终执行的就是 handleMessage,该方法接受到Message 对象并进行处理。至此,消息从发送到接受处理就完成。
网友评论