Handler介绍
Handler
是 Android 下异步线程通讯的主要机制,关于 Handler
的简单介绍如下图所示
在 Handler
机制中,主要的参与对象以及关系在上图中已经很清晰了,我这里在简单介绍一下:
Handler
异步消息的发送者,也是消息的处理者,但是值得注意的是发送的处理可以在不同线程MessageQueue
线程安全的消息队列,线程的变换主要是在MessageQueue
中完成Messager
异步通信内容的载体Looper
通过循环不断的从MessageQueue
中获取消息,然后分发给Handler
处理,和MessageQueue
是一一对应的关系
简单的介绍到此为止,下面开始详细介绍整个消息发送过程。
Handler消息机制
Handler创建
针对 Handler
消息机制,我这边直接从 Handler
构造函数开始解析
public Handler(Callback callback, boolean async) { |
上面这一段代码看似很多,其实就是告诉我们如果想要创建 Handler
就得先有一个 Looper
, Looper
是跟线程绑定的,创建 Looper
的同时它也会把 MessageQueue
也一起创建好,我们平时在主线程中的用的时候不要 Looper
,是因为主线程以及帮我们干了。
public final class ActivityThread { |
到现在可以确定线程、Looper
、Handler
、MessageQueue
的关系如下
graph TB |
消息发送
使用 Handler
发送消息可以有多种形式,Handler.sendMessage()
、Message.sendToTarget()
以及类似的一些方法都可以发送消息,但是不管是哪种方法最终都会调用Handler.enqueueMessage()
方法。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { |
这个方法也没有做太多逻辑处理,直接调用了 MessageQueue
的 enqueueMessage
方法
boolean enqueueMessage(Message msg, long when) { |
这一段事实上就是一个单链表插入,mMessages
为链表头,如果链表为空则直接把 msg
赋给表头,否则通过循环找到链表最后进行插入。MessageQueue
的消息在 Looper.loop()
来获取并处理的。
public static void loop() { |
loop()
方法主要就是在一个无限循环中不断的通过 next
获取消息,然后使用 dispatchMessage
把消息交回给Handler处理。现在我们回头来看 next
方法是如何获取消息的。
Message next() { |
next
方法的主要逻辑都在一个无限循环内,知道获取到消息才会返回,同时把消息从链表中移除。同时默认获取的是链表头,只有当 msg.target == null
时才会获取链表后第一个同步消息,但是要知道我们通过 Handler
发送的消息 target
都是 Handler
本身,事实上这是消息屏障机制
同步屏障
事实上消息分为同步和异步两种,通过 isAsynchronous
来判断,我们平时使用的一般是异步消息 ,同步消息主要用于页面绘制等对时间敏感的地方,但是在通常情况下即使我们使用 setAsynchronous(true)
来手动设置一个同步消息它也不会生效,MessageQueue
还是会把他当作普通消息处理,只有配合 postSyncBarrier
添加一个同步屏障之后才能使用。
public int postSyncBarrier() { |
postSyncBarrier
是一个隐藏 Api,我们无法调用,但这不妨碍我们分析它,它直接向 MessageQueue
的单链表中头插入了一个 target==null
的消息,也就是上一节 next
方法中的逻辑,当这种情况下,MessageQueue
会忽略所有的异步消息,只获取同步消息,需要调用 removeSyncBarrier(int token)
才能取消这个同步屏障,目前同步屏障主要是在 ViewRootImpl
绘制时使用。