Handler源码解析


正文

相信大家在Android的学习或工作中一定用到过Handler,今天我们就从源码角度来分析一下Handler的工作原理。

在Handler的工作过程中,有几个非常重要的角色,分别是Handler、Thread、Looper、MessageQueue,他们的关系如下图所示:

在Android应用程序的入口ActivityThread.main方法里,会自己创建UI线程的Looper、Handler、以及MessageQueue,并且执行消息循环


我们跟进一下,Looper.java中创建消息循环和执行消息循环对应的源码。


首先我们可以看到,MessageQueue是在构造方法Looper中创建的。而这个构造方法是在prepare方法中调用的,也就是说,在prepare方法中创建了一个Looper(创建Looper的时候顺便创建了一个MessageQueue),然后调用sThreadLocal.set(new Looper(quitAllowed))将Looper设置给ThreadLocal。接下来我们看看prepareMainLooper方法


先调用了prepare方法,然后将刚刚设置的ThreadLocal的Looper对象赋值给了sMainLooper。这便是Looper里面创建Looper的过程。接下来我们看看执行消息循环的源码

可以看到,先拿到我们刚刚创建的Looper和消息队列MessageQueue,然后在一个死循环中Message msg = queue.next()不断取消息,接着msg.target.dispatchMessage(msg)不断去处理消息。接下来我们看看处理消息的方法dispatchMessage对应的源码


第一个方法handleMessage是我们创建Handler时如果我们要在UI线程中做一些操作,可以重写这个方法。dispatchMessage只是一个分发的方法,如果Runnable类型的callback为空则执行handlerMessage来处理消息,该方法为空,我们会将更新UI的代码写在该函数中;如果callback不为空,则执行handleCallback来处理,该方法会调用callback的run方法。其实这是Handler分发的两种类型,比如我们post(Runnable callback)则callback就不为空,当我们使用Handler来sendMessage时通常不会设置callback,因此也就执行handlerMessage这个分支。

接下来我们看看创建Handler的过程,一般我们在主线程中都是直接创建Handler


从源码中我们可以看到,创建Handler的构造方法中通过mLooper = Looper.myLooper();去拿到当前的Looper,而上面分析过,UI线程中会自动创建Looper对象,这就是我们为什么在主线程中创建Handler的时候不需要创建Looper对象,而在子线程中创建Handler时候需要收到创建Looper对象,否则会抛异常。在子线程中创建Handler的方式如下


上面我们有提到ThreadLocal,接下来我们简要分析一下:

ThreadLocal是一个关于创建线程局部变量的类,支持泛型。

通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。而使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。

Looper中是这样使用的

ThreadLocal提供了线程本地变量,它可以保证访问到的变量属于当前线程,每个线程都保存有一个变量副本,每个线程的变量都不同,而同一个线程在任何时候访问这个本地变量的结果都是一致的。当此线程结束生命周期时,所有的线程本地实例都会被GC。ThreadLocal相当于提供了一种线程隔离,将变量与线程相绑定。ThreadLocal通常定义为private static类型。看看set方法


Thread.currentThread()方法获取了当前的线程引用,并传给了getMap(Thread)方法获取一个ThreadLocalMap的实例


ThreadLocal会导致内存泄露吗?

首先ThreadLocal实例被线程的ThreadLocalMap实例持有,也可以看成被线程持有。 如果应用使用了线程池,那么之前的线程实例处理完之后出于复用的目的依然存活 所以,ThreadLocal设定的值被持有,导致内存泄露。可是ThreadLocal并不会产生内存泄露,因为ThreadLocalMap在选择key的时候,并不是直接选择ThreadLocal实例,而是ThreadLocal实例的弱引用。

微信公众号请关注:


记得关注wu小鹏哦~


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值