handler机制能够说是android面试时必考的一项,其思想仍是比较nb的,最近和组内的ios同事聊天时,发现ios也有一套相似的机制,可见handler机制的重要性。在了解事后,作一个简单的总结,加深本身的印象。android
1、handler机制相关概念面试
在聊handler机制以前,咱们要先明确一些概念。
数据结构
一、主线程(UI线程)
oop
当程序第一次启动时,android会同时启动一条主线程(main thread),主线程主要用于处理UI相关事件spa
二、Message(消息)
.net
handler接收和处理的对象,经过获取message中携带的信息,作相关处理线程
三、ThreadLocal
对象
线程内部数据存储类,负责存储和获取本线程的looperblog
四、Message Queue(消息队列)
采用单链表的数据结构来存储消息列表,用来存放handler发出的message,遵循先进先出原则
五、handler(处理者)
Message的主要处理者,用来发送message和处理looper取出的message
六、Looper(循环器)
是MessageQueue和handler之间的桥梁,从MessageQueue取出消息给handler
2、Looper源码解析
主线程在activity启动时就建立好了,启动时回调用looper里的两个主要方法,prepareMainLooper和loop方法。
能够看到,prepareMainLooper方法调用了prepare方法,而且调用后会检测sMainLooper是否为空,若是不为空则会抛异常。为空则经过myLooper方法来获取looper。而同时,prepare方法先检测了sThreadLocal里是否有looper,有则抛异常,没有则新set一个looper。可见在这个过程当中,要求sThreadLocal里是不容许有looper的,须要新建一个。从myLooper方法中能够看出,sMainLooper的looper正是取的新建立的looper。
再看looper的构造方法,发如今里面new了一个消息队列,同时把当前线程做为数据持有。这张图里的这几个成员变量应该就是几个核心变量了。一个looper中,持有主looper,looper线程池,消息队列以及当前线程。
对于looper线程池,还要看下面这些源码。
这是ThreadLocal的源码,泛型T接收的就是looper。经过这两个关键方法咱们能够看出,从looper线程池里获取loopera时,经过get方法。而ThreadLocal自己维护一个map,以线程为key,looper为value。当该线程做为key,没法从map中取出looper时,会调用setInitialValue方法,以该线程做为key,存放一个新建的value。而这个get方法告诉咱们,ThreadLocal是经过这种方式来维持每一个线程都有一个本身独立的looper。
3、Looper循环
老规矩,先上图,loop循环的源码比较长,截了两张图
能够看到,loop方法一开始先获取looper,以后获取looper中的message queue。以后是一个for无限循环,不断地从message queue中取消息。使用message queue中的next方法。
而MessageQueue中的next方法是取出本身维护的message链表的第一个,而后将后续的message在排列。
同时咱们注意到,取出的msg,会调用其本身target中的dispatchMessage方法。这个target,不少人应该想到,其实就是handler。handler与msg的绑定,是在handler发送msg时最终调用enqueueMessage时绑定的。而handler在建立时,就会经过Looper.mylooper方法获取当前线程的looper。而looper里又持有messageQueue。这样一切就都联系起来了。
4、整体流程
当咱们建立一个handler时,会调用looper的mylooper方法来得到当前线程的looper。若是没有,就会新建一个looper并存放在looper线程池里,保证每一个线程都有本身惟一的looper。而looper中持有MessageQueue,当新建一个Message时,经过handler发送时,会将这个Message存放到MessageQueue中,而loop方法一直在循环从messageQueue中取消息,发送的message会被取到,并处理。当发送了多个message时,会遵循先进先出原则维持在messageQueue中。那么,不一样线程中发送的message,最终是怎么在主线程中完成处理的呢。要从target的dispatchMessage方法中找答案。
5、主线程更新
这是handler中dispatchMessage的源码,能够看到dispatchMessage的处理有三个优先级,先处理handleCallback方法,若是没有实现callback,则执行mCallback里的handleMessage方法,若是mCallback为空,则最终执行handler的handleMessage方法。这个方法在上面,一看居然为空。咱们恍然大悟,原来,这个不是咱们在建立handler时就重写的方法吗。
这下一切就都说得通了,handler是在主线程中建立的,其实现方法也是主线程中完成的,咱们的message绑定的handler是主线程中的,因此天然处理时就会到主线程中执行。那么有没有在线程中建立的handler的状况呢。有人试过会报错。不过我想经过主线程中的handler已经能够帮咱们解决大部分问题了,咱们只要在子线程中回调方法便可实现主线程刷新。
6、loop无线循环原理
若是一个looper无线循环,无论它是主线程中仍是子线程中,都会形成资源的浪费,以及耗时。那么为何loop方法可以一直循环呢。是由于loop在取不到消息时,会进入阻塞状态,该状态不会占用资源。这部分后续应该单独开一个线程的专题来详细解答。
好了,本篇handler机制写到这里就结束了,相信读者对于handler机制及流程,应该有一个大体的了解了。