Handler源码解析

1、将Message放入消息队列前,将Message中的target指向当前handler

2、放入消息队列

p == null,说明原本是空队列,when == 0 说明当前消息可以立即执行,when < P.when说明第一个元素到了执行时间所以如果队列阻塞需要唤醒

3、如果不满足上述三个条件,就对新的msg寻找插入点

插入到即将处理的msg后面

4、如果需要就唤醒线程

5、Looper的初始化

这里需要掌握ThreadLocal知识点

这里我们简单说下,首先sThreadLocal是个静态变量,所以不同的Looper对象其sThreadLocal是同一个,这样sThreadLocal.get() != null就可以确定已经初始化过,从而抛出异常

而其set的过程

所以一个线程只会有一个looper否则就会抛出运行时异常,因为在ThreadLocalMap中的key是sThreadLocal是唯一的,那么不同线程是否会抛出运行时异常 呢,显然 不会,因为从t.threadLocals说明threadLocals只是线程的一个成员变量。

这里ThreadLocalMap也与其他Map不同,一个是节点继承了弱引用,一个是hash取值

接下来看下Looper.loop()

先从消息队列中获取msg,如果不到执行时间则阻塞,如果到了就返回msg,如果为空就无限阻塞,直到有新的消息到来唤醒线程

接下来要回到主线程了,所以日志记录下消息执行的时间,性能优化、ANR均可设置logging

上文已经说到target就是我们放入消息队列的handler

那么到这里在说handler内存泄漏已经一目了然了,因为looper在主线程的在与队列绑定是消息队列是不允许退出的,那么主线程的虚拟机栈帧的局部变量表(GCRoot)中会持有looper,持有消息队列,sMainLooper是个静态变量也能当做GCRoot持有handler,而handler是匿名内部类隐士持有activity,这样activity就无法回收

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值