美文网首页
Handler 源码解析

Handler 源码解析

作者: 小名坎坎 | 来源:发表于2019-03-19 14:22 被阅读0次

Handler基础组成结构 

    1.Handler  -- 发送消息,处理消息

    2.Message -- 线程之间传递的消息,它可以在内部携带少量的数据,用于线程之间交换数据

    3.MessageQueue --- 消息队列(实际是单链表的数据结构)--- 消息存储单元 --- 以队列的形式对外提供插入和删除操作

    4.Looper -- 线程默认是没有Looper的,如果需使用Handler就必须为线程创建Looper--消息循环

    5.ThreadLocal -- 可以在每个线程中互不干扰的存储和提取数据 --- 获取每个线程的Looper

源码解析

ThreadLocal -- 一个线程内部的数据存储类

            主要提供了 set(T value)  和 get()方法

set()方法

              把数据存储当前线程中,至于内部数据的存储结构,有兴趣可以深入看一下,在这就不做阐述,我们只需知道,这里是存储数据的并且与当前线程绑定。

get方法

 get()在当前线程中取出数据。TheadLocal的好处是在不同线程中维护一套数据的副本并彼此互不干扰。TheadLocal在Handler消息机制扮演的角色就是管理每个线程的Looper。

MessageQueue --- 通过一个单链表的数据结构来维护消息列表     

MessageQueue顾名思义消息队列,至于他为什么使用单链表,无非是因为单链表在插入和删除上比较占优势,他的作用就是管理handler的消息,下面我们来看一下这个类中的两个重要方法。

(1)enqueueMessage(Message msg, long when)  插入队列---也就是插入链表

enqueueMessage()方法中部分代码 单链表

我们需要找出插入msg的节点,所以if()判断是否插入表头,else中就要根据p.when来查找处在列表中合适的节点,然后进行插入操作。至此一条需要处理的消息就已经插入了。

(2)next() -- 取出消息

            我们查看源码的时候 会发现方法中是一个无限for循环,我们现在的目的着重于找到这么取出消息的流程,其他的先忽略,我们可以看到下面这段代码   

next()方法中部分代码,没有截全,请自行查看源码

mMessage 是单向链表的第一个元素。

我们可以看出上面这段代码有两个判断,我们先看一个第一个判断if(msg !=null && msg.target ==null) ,前一个条件就不做阐述了,后面这个target是什么呢,我们查看message源码的时候就知道了,这其实就是发送消息的hanlder,那么为什么这个值有可能为空呢?我们在messageQueue中看到了postSyncBarrier()这个方法,这个方法是向消息队列插入一个异步消息,并且插入一个屏障并且没有设置target。所以我们在取出队列中消息的时候 要先判断这些异步消息,不然有屏障的存在,哪怕同步消息的执行时间到了,也取不出来。接下来我们看第二个判断,这个判断里面就是根据when来从单向链表中取出需要执行的msg并返回。

Looper --- 扮演着消息循环的角色   

looper不停的从messageQueue中查看是否有新消息,如果有就立刻处理,否则就一直阻塞,他其中也有两个重要的方法。

(1)prepare() 返回一个looper对象,我们在线程中使用looper的时候 必须要先创建一个looper对象,你也许会疑问,我以前使用handler也没有创建过looper啊,那是因为在ui线程也就是ActivityThread被创建时初始化了Looper,有兴趣的可以去看一下。

(2)loop() 开始查看 

loop()方法部分一

这里的主要作用时调用messageQueue中的 next方法取出需要执行的msg。

loop()方法部分二

这里的主要作用就是取出方法后返回给handler处理,我们在上文中说过,target就是handler对象。

Handler --- 消息的发送和接收

其中包括:初始化、发送、接受 等

初始化:我们日常调用中可以通过callback回调使用handler,也出可以生成派生类使用 

发送:我们调用post和send系列的的方法来发送消息,实际上post最后也是在调用send,这些其实就是在往消息队列中插入消息。

接收:我们还看到handler中有个dispatchMessage(Message msg)方法,这个方法就是在上面Looper.loop()中的调用的,然后在这个方法中处理消息。

小结:1.我们一条message通过handler发送出去

           2.插入messageQueue

           3.looper 轮循队列,取出message

           4 回调给handler处理

最终回到Handler是如何实现线程之间的切换的呢?

重点在于looper,因为looper是在当前线程中调度的,不管你是在哪个线程使用handler.send来发送消息,最后都会在looper实例所在的线程中执行

至此,hanlder消息机制的基本架构都介绍完了,这里介绍的只是基本的流程。

相关文章

网友评论

      本文标题:Handler 源码解析

      本文链接:https://www.haomeiwen.com/subject/grtgmqtx.html