美文网首页
Handler+Messagequeue+looper

Handler+Messagequeue+looper

作者: 李海洲 | 来源:发表于2017-06-04 11:35 被阅读0次

    本文讨论Android的消息机制,基于Android7.1代码,旨在通过本文对Android的消息机制有一个基础的认识
    主要分三部分进行讨论:Handler、Looper、MessageQueue
    Part1:Handler部分 【frameworks/base/core/java/android/os/Handler.java】
    Handler的sendMessage方法层层跟进最终调用到了sendMessageAtTime方法,如下所示


    图片.png 图片.png 图片.png

    这里的Queue来自于looper


    图片.png

    从此处代码可以看出,Handler与Looper,和MessageQueue正是在此处关联起来的


    图片.png

    Part2:Looper部分【frameworks/base/core/java/android/os/Looper.java】


    图片.png

    另外,再看下Looper的构造函数

    图片.png

    MessageQueue包装在了Looper对象中

    由此可以看出,通过ThreadLocal使得线程和Looper关联上,因为MessageQueue包装在了Looper对象中,从而消息队列与线程关联上,并且不同的线程就不能访问对方的消息队列。
    三者关系图如下

    图片.png 图片.png

    这里说下TLS即线程局部存储(Thread Local Storage,TLS),通过TLS机制,为每一个使用该全局变量的线程都提供一个变量值的副本,每一个线程均可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。而从全局变量的角度上来看,就好像一个全局变量被克隆成了多份副本,而每一份副本都可以被一个线程独立地改变。
    这里的代码就是为每个线程创建一个自己的Looper副本,而不用synchronized同步机制来处理,A线程改变了A的looper副本,不影响B线程的Looper,从而比较高效的实现线程安全。

    上面代码可以看出在Looper准备好后,线程会调用Looper.loop(),进入真正的循环机制。loop()函数的代码流程非常简单,只不过是在一个for循环里不停从消息队列中摘取消息,而后调用msg.target.dispatchMessage()对消息进行派发处理而已。
    这里的msg.target域比较重要,这个域记录的其实就是当初向消息队列发送消息的那个handler。

    Part3:MessageQueue部分【frameworks/base/core/java/android/os/MessageQueue.java】
    Handler的sendMessageAtTime()时,最终会调用queue.enqueueMessage()将消息push进消息队列
    这里对消息链表里如何插入Message,以及消息队列如何感知消息变化的,这里不多加介绍,牵涉到管道和epoll机制。可以自行阅读MessageQueue.java的enqueueMessage方法追下去

    这里顺便说下我们平时定义Handler的较好做法


    图片.png

    小结:
    通过Handler向Looper的消息队列中插入Message,而后再由Looper在消息循环里具体处理。因为消息队列本身不具有链表一变动就能马上感知的功能,所以它需要借助管道和epoll机制来监听变动。当外界向消息队列中打入新消息后,就向管道的“写入端”写入简单数据,于是epoll可以立即感知到管道的变动,从何激发从消息队列中摘取消息的动作。这就是Android消息机制的大体情况。

    本文参考文章
    https://my.oschina.net/youranhongcha/blog/492591
    http://www.jb51.net/article/81932.htm

    相关文章

      网友评论

          本文标题:Handler+Messagequeue+looper

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