Handler机制源码解析
2017-07-31 本文已影响76人
Wynne丶XXW
做为一个Android Develop,在我们的日常开发中,经常会和Handle打交道,比如最常见的更新UI界面。Handle机制做为Android的消息机制,也是面试中最常见的一道面试题,今天我们就抛开API,来看看他的源码吧.
主要成员
- Handle: 线程之间的消息机制,可以做为主线程和子线程的切换,比如网络请求数据,更新UI界面
- Looper : 消息轮播器,会以死循环的方式一直查找是否有新消息。没有则等待
- ThreadLocal: 这里可以理解为线程的存储器
- MessageQueue: 消息队列,顾名思义MessageQueue就是以消息队列的来进行,增加与删除
- Message: MessageQueue的成员变量 一个消息实体
流程分析
-
首先我们从最常规的发送消息sendMessage(msg)开始分析
- 当我们发送消息的时候 点进源码之后再 经过一系列的跳转 我们会拿到MessageQueue的enquequMessage方法来进行入队操作,这个时候可能就会有同学会问,这个MessageQueue是怎么来的呢? 很简单我们接下来看一下MessageQueue 是如何产生的
-
可以看到 在我们new Handle的时候 最终会调用这个构造函数,通过Looper.myLooper这个静态方法会创建一个mLooper的对象,然后会把mQueue这个成员变量赋值给MessageQueu. 接下来我们在接着看myLooper()这个静态方法
-
myLooper这个方法 看上去好像是在一个容器里面获取到的Looper,有一点像我们经常写的get方法,其实里的sThreadLocal也是这个意思,ThreadLocal 是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,而且只有在指定的线程中可以获取到存储数据。
- prepareMainLooper()这个方法是在AndroidThread中调用的,就是Android的入口,这里会去调用prepare()这个方法 ,如果我们的mThreadLocal存在Looper它就会抛出一个异常,就是说一个线程只能存在一个Looper,没有的话我们就会new 一个Looper存在ThreadLocal中。
- 接着我们在来看Looper的构造函数,这个时候我们就明白了发送消息时的MessageQueue是从哪里获取到的.接下来,我们就看一下Message是如何入队的。
- 这里我们省去了很多无关代码,只看Message是如何插入到MessageQueue里面的, 这里它的主要操作就是单链表的插入操作,就不做过多解释了。感兴趣的同学可以去看看数据结构,接下来 我们看一下Looper是如何取出消息然后回调给Handle。
上面图片来自http://blog.csdn.net/u011507982/article/details/56559398
- 在Android主函数的入口处 我们可以看见调用了prepareMainLooper()方法,根据上面的分析,我就可以得知我们创建了一个Looper对象,然后我们在看望下面看,又调用了Looper.loop()这个方法,其实这个方法,就是开启我们的循环 ,去查找消息队列中是否有Message。
- 通过message的next方法,我们可以得到MessageQueue里传入的message,然后我们通过Message的成员变量target.dispatchMessage(msg)进行了回调,target这个成员变量是什么呢? 其实这个就是我们发送消息的Handle对象,那个这个Handle是什么时候传进Message的呢,我们看一下下面这段代码就明白了
-
在我们最开始,创建Handle 发送消息的时候 我们都会调用obtainMessage()来创建一个Message 来存储消息,发送出去,到这个里 我们就明白了。为什么创建消息要用obtainMessage()这个方法了。
- 在Looper的loop()方法中 我们最后会调用Message.tagert.dispatchMessage()这个方法,来回调handleMessage()来处理我们发送的消息。
总结
今天我们学习了Handler的消息机制,再以后的开发中,工作中,我们可以更加灵活的使用Handle来做消息处理,帮助我们更快的完成工作需求。