Handler 常用场景 在 Activity 中定义一个 Handler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 private val mHandler = object : Handler(Looper.getMainLooper()) { override fun handleMessage (msg: Message ) { when (msg.what) { CODE_GET_USER_INFO -> { val user = msg.obj as User textViewName.text = user.name textViewSite.text = user.site imageViewIcon.load(user.icon){ transformations(CircleCropTransformation()) } } } } }
在子线程获取到数据之后通过 Handler 将数据传到 UI 线程进行处理
1 2 3 4 5 6 7 8 9 10 11 12 13 Thread { val request = Request.Builder() .url("http://10.0.2.2:8000/user" ) .build() val response = OkHttpClient().newCall(request).execute() val result = response.body?.string() val user = Gson().fromJson(result, User::class .java) Message.obtain().also { it.what = CODE_GET_USER_INFO it.obj = user mHandler.sendMessage(it) } }.start()
打开 Handler 源文件,可以看到这样的注释
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.
简单概述一下,Handler 两个用途:(1)在未来某个时间点执行事件 (2)跨线程执行事件
源码分析 Handler 构造函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public Handler (@NonNull Looper looper) { this (looper, null , false ); } final Looper mLooper;final MessageQueue mQueue;final Callback mCallback;final boolean mAsynchronous;public Handler (@NonNull Looper looper, @Nullable Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; } public interface Callback { boolean handleMessage (@NonNull Message msg) ; }
在 Handler 的构造函数中初始化了两个重要的成员变量:mLooper 和 mQueue
我们传人的参数是 Looper.getMainLooper(),代码如下
1 2 3 4 5 6 7 private static Looper sMainLooper;public static Looper getMainLooper () { synchronized (Looper.class) { return sMainLooper; } }
Looper 中的 sMainLooper 又是在哪里初始化的呢?我们看 ActivityThread 这个类中的 main 函数
1 2 3 4 5 6 7 public static void main (String[] args) { ... Looper.prepareMainLooper(); ... Looper.loop(); throw new RuntimeException ("Main thread loop unexpectedly exited" ); }
prepareMainLooper() Looper 的 prepareMainLooper 函数以及后续相关函数调用
1 2 3 4 5 6 7 8 9 10 11 12 13 public static void prepareMainLooper () { prepare(false ); synchronized (Looper.class) { if (sMainLooper != null ) { throw new IllegalStateException ("The main Looper has already been prepared." ); } sMainLooper = myLooper(); } } public static Looper myLooper () { return sThreadLocal.get(); }
实际上调用了 prepare 函数。
1 2 3 4 5 6 7 8 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal <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)); }
1 2 3 4 5 6 7 final MessageQueue mQueue;final Thread mThread; private Looper (boolean quitAllowed) { mQueue = new MessageQueue (quitAllowed); mThread = Thread.currentThread(); }
至此,我们可以确定,在 ActivityThread 执行的时候,初始化了 Looper,并且初始化了 Looper 中两个成员变量:消息队列 和 当前线程对象。
值得注意的是:
一个线程只能创建一个 Looper,也就是说线程和 Looper 是一一对应的,且它俩是有一定的绑定关系的
Looper 中有一个 ThreadLocal 数据结构,用来存储线程和 Looper,维系两者的绑定关系
我们看一下 ThreadLocal 的相关代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public T get () { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null ) { ThreadLocalMap.Entry e = map.getEntry(this ); if (e != null ) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); } public void set (T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null ) map.set(this , value); else createMap(t, value); } void createMap (Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap (this , firstValue); } ThreadLocalMap getMap (Thread t) { return t.threadLocals; } static class ThreadLocalMap { static class Entry extends WeakReference <ThreadLocal<?>> { Object value; Entry(ThreadLocal<?> k, Object v) { super (k); value = v; } } ... private Entry[] table; ... }
可以看出,ThreadLocal 中有个 ThreadLocalMap 类,它其实跟 Map 没啥关系。ThreadLocalMap 有个继承于 WeakReference 的内部类 Entry 用来存储 Looper,而 ThreadLocalMap 是赋值给 Thread 的成员变量 threadLocals 的。
那么也就是通过这种方式实现了一个线程和一个 Looper 的绑定。
Looper.loop() 初始化的动作做完之后,执行了 Looper.loop()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public static void loop () { final Looper me = myLooper(); if (me == null ) { throw new RuntimeException ("No Looper; Looper.prepare() wasn't called on this thread." ); } if (me.mInLoop) { Slog.w(TAG, "Loop again would have the queued messages be executed" + " before this one completed." ); } me.mInLoop = true ; ... for (;;) { if (!loopOnce(me, ident, thresholdOverride)) { return ; } } }
1 2 3 4 5 6 7 8 9 10 private static boolean loopOnce (final Looper me, final long ident, final int thresholdOverride) { Message msg = me.mQueue.next(); if (msg == null ) { return false ; } ... msg.target.dispatchMessage(msg); ... }
我们可以看到 loop 函数中执行了一个死循环,不断的执行 loopOnce 函数。
在 loopOnce 函数中我们需要注意 2 点:
Message msg = me.mQueue.next();
msg.target.dispatchMessage(msg);
mQueue.next() 注意看 next 后面的的注释 might block
,这个函数是会阻塞的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 Message next () { ... for (;;) { ... nativePollOnce(ptr, nextPollTimeoutMillis); synchronized (this ) { final long now = SystemClock.uptimeMillis(); Message prevMsg = null ; Message msg = mMessages; if (msg != null && msg.target == null ) { do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } if (msg != null ) { if (now < msg.when) { ... } else { mBlocked = false ; if (prevMsg != null ) { prevMsg.next = msg.next; } else { mMessages = msg.next; } msg.next = null ; msg.markInUse(); return msg; } } ... } ... } }
这里可以看到,next 其实也是执行了一个死循环,不断的取出下一个 Message ,判断其出发时间是否符合,然后将其返回。倘若没有 Message ,nativePollOnce 会阻塞该函数,直到新的 Message 进入 MessageQueue。
msg.target.dispatchMessage(msg) 取到符合触发时间的消息后,会执行该函数。查看 Message 类我们会发现,它有一个成员变量
然后执行了 Handler 的 dispatchMessage 函数,传入了当前触发的 Message。
有 2 点需要理解:
Message 中的 target 是什么时候初始化的
Handler 中的 dispatchMessage 做了什么
回头看最开始简单的使用案例,我们执行了 mHandler.sendMessage(it) 将消息进行发送,进入该函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public final boolean sendMessage (@NonNull Message msg) { return sendMessageDelayed(msg, 0 ); } 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); } private boolean enqueueMessage (@NonNull MessageQueue queue, @NonNull Message msg, long uptimeMillis) { msg.target = this ; msg.workSourceUid = ThreadLocalWorkSource.getUid(); if (mAsynchronous) { msg.setAsynchronous(true ); } return queue.enqueueMessage(msg, uptimeMillis); }
最终调用了 enqueueMessage 将当前 Handler 对象赋值给此次 Message 的 target,并将消息添加到消息队列。
需要注意的是 MessageQueue 中的 enqueueMessage 函数中,除了将 Message 添加到消息队列,还在某些条件下执行了一个函数 nativeWake()
,这个函数就是对应上文中 nativePollOnce()
的,将阻塞唤醒。
最后我们再看 dispatchMessage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public void dispatchMessage (@NonNull Message msg) { if (msg.callback != null ) { handleCallback(msg); } else { if (mCallback != null ) { if (mCallback.handleMessage(msg)) { return ; } } handleMessage(msg); } } private static void handleCallback (Message message) { message.callback.run(); }
其实是将消息进行分发消费。这里主要有 3 种消费方式
Message 中的 callback(其实是一个 Runnable ) 通过 run 进行处理
Handler 中的 Callback 通过 handleMessage 进行处理
直接通过 Handler 中的 handleMessage 进行处理
这也对应 Handler 的三种使用方式。
Handler 的三种使用方式
1 2 3 4 5 6 7 8 9 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; }
Handler(Looper looper, Callback callback)
1 2 3 public Handler (@NonNull Looper looper, @Nullable Callback callback) { this (looper, callback, false ); }
1 2 3 4 private val mHandler = object : Handler(Looper.getMainLooper()) { override fun handleMessage (msg: Message ) { } }
总结 关于 Handler 大致可以分为 3 个阶段去理解
初始化阶段 在创建 Handler 对象的同时,会初始化 Looper 和 Looper 中的 MessageQueue。 Looper 的初始化包括对象创建和 loop() 调用。
Looper 的初始化涉及到 Handler 所工作的线程,井且会将 Looper 对象存储在 Threadlocal 中,再赋值给该线程的成员变量。这样线程和 Looper 就建立了绑定关系,且一个线程最多只能创建一个Looper,初始化多次会拋出异常。值得注意的是在 UI 线程是不需要调用 Looper.prepare() 去初始化的,因为在ActivityThread 的 main 函数,也就是APP进程启动入口里面,已经执行了 Looper.prepareMainLooper() 和 Looper.loop()。
loop() 调用其实就是执行了一个死循环,然后从 MessageQueue 中取出 Message, 取到了就发给 Handler 去处理,取不到就阻塞。
消息发送 通过 Handler 将 Message 加入 MessageQueue。
这里首先会将 Handler 与 Message 进行绑定,以便后续 Message 取出后交给Handler 进行处理
按照 Message 的执行时间将其插入到 MessageQueue 中
消息分发 在loop()循环中检查到符合执行时间的 Message 后,这里对应 Handler 的不同构造方法和消息发送方式有 3种分发情况。
handler.post(Runnable n),优先判断 Message 中是否有 Runnable对象,有的话执行其 run 方法
Handler(Looper looper, Callback callback),其次再判断是否在创建 Handler 的时候传入了 Callback,如果有,执行其 handleMessage 方法
上述两种都不满足的话,执行 Handler 自身的 handleMessage 方法