Android中Handler机制原理浅析

对于我们来说Handler机制是日常开发中经常用到的,我们可以使用它轻松实现线程间的切换和延时操作。今天我们就来分析一下Handler的实现原理。我们先来看一下Handler机制的中重要的四个类和一个工具。
Handler 用于消息的发送和接受消息
Message 消息
MessageQueue 单向绑定的消息列表
Looper 消费消息
ThreadLocal 数据储存

一、ThreadLocal

ThreadLocal主要作用是将数据绑定当线程上,接下来我们主要是看它的get和set方法。

上面的get方法中会先获取当前线程,然后以该线程为key去查找对应的Value,如果Value为null时会返回setInitialValue()方法中的值,其实setInitialValue()方法放回的就是一个初始值默认为null我们可以通过重写initialValue()方法来设置初始值。

set方法就简单多了,它就是以当前的线程为key进行数据的存储。这样就能把数据绑定到线程上了。

二、Message

消息对象就是一个数据类。Message的创建方法有两种,一个是直接使用new关键字另一个就是通过obtain方法进行创建了。两个种方法有什么区别呢为什么推荐我们使用obtain方法创建Message。我们分析obtain方法的时要对应的看一下它的回收方法recycleUnchecked

如果我们直接去看obtain方法的话可能理解起来有一定的困难。我们可以先从它的回收方法开始分析。我们主要看一下回收方法中同步代码块的代码,它先判断sPoolSize是否小于MAX_POOL_SIZE,sPoolSize的初始值为0 MAX的值为50 接下来就是next = sPool;next和sPool的类型都是Message,sPool是个静态的属性。他将要回收的message的next赋值为sPool再将Message赋值给静态属性sPool然后sPoolSize++,他这是干呢?其实sPool是Message内部的一个大小为50的单向缓存列表。执行回收方法时先判断缓存列表的个数,如果小于50就将回收的Message添加到列表中。
知道sPool是一个缓存列表之后我们再去分析obtain方法就简单了,它就是先去sPool中去取缓存,没有缓存时就通过new 关键字来创建一个新的返回。
Message中的target属性我们也要知道,他是用于存储发送该消息的handler。在handler发送消息时进行的赋值。

三、Handler

Handler的作用就是进行消息的发送与接送。

我们先看一下Handler创建过程中都做了什么。

标注1处就是通过ThreadLocal获取当前线程绑定的Looper。这里有一个常见的问题就是在子线程中为什么不是直接使用Handler,就是因为在子线程中创建Handler时不能获取子线程对应的Looper从而抛出了异常,那为什么子线程不能直接创建Handler而主线程却可以呢?这个我们在Looper那里进行分析。标注2处就是获取Looper中的MessageQueue赋值给成员变量mQueue。接下来看一下发送消息的过程。

handler发送消息的方法有很多个,但都是在计算出一个时间戳之后去调用了enqueueMessage方法。方法中为msg.target赋值为当前的handler。最后调用MessageQueue的enqueueMessage方法将消息添加到消息列表中。以上就是handler发送消息的过程。对于handler接受消息的过程我们在Looper中进行分析,大致过程就是Looper拿到消息后调用通过message的target获取对应的handler再调用handler的dispatchMessage方法回调我们重写的方法。

四、Looper

Looper的作用就是循环的取出MessageQueue中Message并将他们分发给对应的Handler。
在讲Handler的时候我们说到没什么主线程中可以取到Looper而子线程中就取不到呢。这是因为系统在ActivityThread的main方法中进行了创建,我们看一下main方法。

在main方法中主要是调用了Looper的prepareMainLooper方法和loop方法。我们先看一下prepareMainLooper方法

prepareMainLooper方法就是创建了Looper并将该Looper保存到了ThreadLocal中,同时创建了对应了的MessageQueue。这样主线程上面就绑定了一个Looper。那我们我们要想在子线程中使用handler的话要手动调用Looper.prepare()在子线程中创建一个Looper,然后调用loop方法开启循环。

loop方法比较长我们主要看四个地方就可以了,标注1 在调用loop方法后会开启一个死循环。标注 2 此处调用了MessageQueue的next方法来获取列表中的消息,没有事消息时阻塞。标注3 获取到message后通过它的target属性获取对应的handler并调用dispatchMessage方法。标注4 message处理完成后调用它的回收方法。

五、MessageQueue

用于存储消息。我们主要看一下它的储存方法和取出方法。先看他的储存方法。

它主要是通过when这个是延时时间来判断message添加到mMessage中的位置。mMessage也是一个单项列表。

next方法比较长它的主要功能就是循环的返回列表中的message,没有值的时候通过native方法就行阻塞。

六、总结

我们对Handler机制中的各个部分进行了逐一的分析,已经大概知道各部分的作用及整个机制的运作过程。可以用下图简单表示。


该文档是自己的学习记录如有错误欢迎指出。

你可能感兴趣的:(Android中Handler机制原理浅析)