基于Android 8.1(API27) 源码,分析 Handler 的工作流程。
在 Android 系统中,Zygote 进程是首个 java 进程,同时也是所有 java 进程的父进程。上层应用开发工程师所关注的 App 进程 fork 自 Zygote 进程,App 进程创建后最后会通过反射,调用 ActivityThread 的 main() 方法,进而初始化主线程的 looper 和 handler。
ActivityThread.java
public static void main(String[] args) { // 省略... // 初始化 UI 线程的 looper 对象 Looper.prepareMainLooper(); // 初始化 ActivityThread,进而初始化其成员变量 mH(Handler子类) ActivityThread thread = new ActivityThread(); // 将 ApplicationThread(Binder) 对象 attach 到 ActivityManagerService(AMS) // 注:AMS 运行在 SystemServer 进程的一个线程中,负责调度四大组件等,通过 Binder 与 App 进程进行 IPC thread.attach(false); // 省略... // 主线程进入循环 Looper.loop(); } 复制代码
Looper.java
public static void prepareMainLooper() { // 初始化主线程 looper,不允许退出 prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } // 初始化 sMainLooper,便于通过 new Handler(Looper.getMainLooper()) 方式向主线程发消息 sMainLooper = myLooper(); } } 复制代码
Looper.java
// sThreadLocal 为 ThreadLocal<Looper> 类型的静态变量 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static void prepare(boolean quitAllowed) { // 一个线程只能有一个 looper 对象,否则抛出异常 if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } // 此处实际是将 looper 对象存储到了 Thread.java 的成员变量 threadLocals(ThreadLocalMap) 中 sThreadLocal.set(new Looper(quitAllowed)); } 复制代码
sThreadLocal
对象是 Looper.java 中的静态变量,故只要 Looper.class 不被 jvm 卸载,该变量就不会重新初始化。
Looper.java
private Looper(boolean quitAllowed) { // 初始化 MessageQueue,因为一个线程只有一个 looper,所以也只有一个 MessageQueue 对象 // 无论 new 多少个 Handler,其成员变量 mQueue 对象皆指向此处创建的 mQueue 对象 mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } 复制代码
ThreadLocal.java
public void set(T value) { // 入参 values 是上面新建的 looper 对象 Thread t = Thread.currentThread(); // 获取当前线程的成员变量 threadLocals ThreadLocalMap map = getMap(t); // 此时 map == null if (map != null) map.set(this, value); else // 走这个分支 createMap(t, value); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; } void createMap(Thread t, T firstValue) { // 入参 firstValue 是上面新建的 looper 对象 // 创建一个 ThreadlocalMap 对象,并把 looper 存至其中,最后赋值给成员变量 threadLocals t.threadLocals = new ThreadLocalMap(this, firstValue); } 复制代码
ThreadLocal 是一个泛型类,此处泛型为 Looper,它能实现每个线程拥有各自的 looper 而不产生竞争的原因是:它将每个线程的 looper 存储到了各自的成员变量 threadLocals 中。
Thread.java
ThreadLocal.ThreadLocalMap threadLocals = null; ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); // 保存 looper 对象 table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); } 复制代码
ThreadLocalMap 是自定义的一个数据结构,由数组实现,其元素类型为 Entry。Entry 保存一个键值对,key 始终为 ThreadLocal<?>
类型,value 为 Object 类型。此处 key 即为 Looper.java 中的静态变量 sThreadLocals,而 value 为之前创建的 looper 对象。
Looper.java
public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } // 初始化 sMainLooper,便于通过 new Handler(Looper.getMainLooper()) 方式向主线程发消息 sMainLooper = myLooper(); } } public static @Nullable Looper myLooper() { return sThreadLocal.get(); } 复制代码
ThreadLocal.java
public T get() { Thread t = Thread.currentThread(); // 获取当前线程的 threadLocals 对象,此处为 UI 线程 ThreadLocalMap map = getMap(t); // 已经调用 prepare(false),此处 map 不为 null if (map != null) { // 这个 this 就是 sThreadLocal ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") // 此处 value 为 Object 类型,需要强转为 Looper 类型 T result = (T)e.value; // 返回该线程的 looper 对象 return result; } } return setInitialValue(); } 复制代码
至此,UI 线程的 looper 对象已经创建并且保存到了 UI 线程的 threadLocals 对象中,并且赋值给了 Looper.java 的静态变量 sMainLooper,以便在其它线程中,通过 new Handler(Looper.getMainLooper()) 方式向主线程发消息。接下来看 Handler 的初始化。
Hanlder.java
public Handler() { this(null, false); } public Handler(Callback callback, boolean async) { // 省略... // Handler 在哪个线程创建,取出来的就是哪个线程的 looper mLooper = Looper.myLooper(); // 未调用 Looper.prepare() 的线程,无法创建 Handler if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } // 指向创建 looper 时所创建的 MessageQueue 对象 mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; } 复制代码
没有 looper 就无法创建 Handler,同样创建 Handler 时也可以为其指定 looper。
Handler.java
public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDelayed(what, 0); } public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { // 从对象池中取出一个 Message 对象 // 注:Message 对象使用后会被回收进对象池(大小为50),以便下次复用 Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); } public final boolean sendMessageDelayed(Message msg, long delayMillis) { // 入参保护 if (delayMillis < 0) { delayMillis = 0; } // 立即发送消息 return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } public boolean sendMessageAtTime(Message msg, long uptimeMillis) { // mQueue 就是这个 handler 所在线程对应的 looper 对象中的 mQueue 对象 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) { // 将 handler 对象赋值给 msg 的 target msg.target = this; // mAsynchronous 默认是 false if (mAsynchronous) { msg.setAsynchronous(true); } // 调用 MessageQueue 的 enqueueMessage() 将消息投入 MessageQueue // 注:不想翻译成消息队列,因为一般说消息队列指的是 Linux IPC 方式的一种。 return queue.enqueueMessage(msg, uptimeMillis); } 复制代码
MessageQueue.java
// MessageQueue 是由单向链表实现的、总是按照 msg.when 升序排序的队列。 // 其成员变量 mMessages 代表表头。 Message mMessages; 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; // 初始状态下,mMessages 为 null Message p = mMessages; boolean needWake; // 如果表头为 null 或者新消息的 when 小于表头的 when,进入这个分支 if (p == null || when == 0 || when < p.when) { // 入参 msg 的下一个节点指向当前表头,即入参 msg 成为新的表头 msg.next = p; // 代表表头的成员变量重新赋值 mMessages = msg; needWake = mBlocked; } else { // 如果表头不为 null 且新消息的 when 大于等于 表头的 when,则进入这个分支 needWake = mBlocked && p.target == null && msg.isAsynchronous(); // 遍历链表,找出下一节点为 null(即表尾) 或者 when 大于等于新消息 when 的节点 Message prev; for (;;) { prev = p; p = p.next; if (p == null || when < p.when) { break; } if (needWake && p.isAsynchronous()) { needWake = false; } } // 如果未找到 when 大于等于新消息 when 的节点,则将 msg 追加到表尾。 // 否则将 msg 插入到该结点之前 msg.next = p; // invariant: p == prev.next prev.next = msg; } // We can assume mPtr != 0 because mQuitting is false. if (needWake) { // 新消息入队,需要唤醒,nativePollOnce() 才能返回 nativeWake(mPtr); } } return true; } 复制代码
MessageQueue 是由单向链表实现的,总是按照 msg.when 升序排序的队列。新发送的消息会插入到发送时间比它晚的消息之前。
Looper.java
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; // 循环读取消息并处理,无消息时阻塞。这种写法是最常用的 Linux IO 操作方式。 for (;;) { // 取出一个消息,若没有消息要处理,则阻塞 Message msg = queue.next(); // 可能阻塞 if (msg == null) { // No message indicates that the message queue is quitting. return; } final long traceTag = me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { // 调用 handler 的 dispatchMassage() 分发消息 msg.target.dispatchMessage(msg); end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } // 回收进对象池 msg.recycleUnchecked(); } } 复制代码
MessageQueue.java
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 循环 for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } // native 层阻塞函数,nextPollTimeoutMillis 为超时时间,首次循环时值为0,即直接返回 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) { // 下一个消息还没到处理时间,则设置超时时间为还需等待的时间,进入阻塞状态. 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 需要取走处理,故需要从链表中断开 msg.next = null; if (DEBUG) Log.v(TAG, "Returning message: " + msg); // 标记为使用中 msg.markInUse(); // 返回要处理的消息 return msg; } } else { // 没有消息要处理,超时时长为-1,循环并等待 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,进入阻塞状态,有新消息入队时,会调用 nativeWake() 唤醒 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(TAG, "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; } } 复制代码
Handler.java
public void dispatchMessage(Message msg) { if (msg.callback != null) { // 如果 msg 的 callback 不为 null,则执行 msg 的 callback handleCallback(msg); } else { if (mCallback != null) { // 如果 handler的 callback 不为 null,则执行 handler的 callback if (mCallback.handleMessage(msg)) { // 如果 callback 的 handleMessage() 返回 true,则不再调用 handler 的 handleMessage() return; } } // 调用 handler 的 handleMessage() handleMessage(msg); } } 复制代码
图片来自 MIUI 系统工程师 Gityuan 的 Android消息机制2-Handler(Native层) 。