作为一个Android开发,Handler机制是一定要了解的。在我面试过程中,发现很多人对Handler和Looper机制非常了解,对答如流, 但 是 却 不 知 道 何 为 HandlerThread
HandlerThread是Thread的子类,严格意义上来说就是一个线程,只是它在自己的线程里面帮我们创建了Looper HandlerThread存在的意义如下:
方便使用:a. 方便初始化,b,方便获取线程looper
保证了线程安全
我 们 一般在Thread里面 线程Looper进行初始化的代码里面,必须要对Looper.prepare(),同时要调用Loop。loop () ;
上面这段代码有没有问题呢?
以上问题
HandlerThread 已经 帮我们 完美的 解决了 ,这就 是 handlerThread存在 的必要 性了。
我们再看看HandlerThread源码
它 的 优点就在于它的多线程操作,可以帮我们保证使用Thread的handler时一定是安全的。
1.Looper 准备和开启轮循: Looper#prepare() 初 始 化 线 程 独 有 的 Looper 以 及 MessageQueue Looper#loop() 开 启 死 循 环 读 取 MessageQueue 中下 一 个 满 足 执 行 时 间的 Message 尚无 Message 的话,调用 Native 侧的 pollOnce() 进入无限等待 存在 Message,但执行时间 when 尚未满足的话,调用 pollOnce() 时传入剩余时长参数进入有限等待
Looper 实 例 被 管 理 在 静 态 属 性 sThreadLocal 中 ThreadLocal 内 部 通 过 ThreadLocalMap 持 有 Looper, key 为ThreadLocal 实 例 本身,value 即为Looper 实例 每个 Thread 都有一个自己的 ThreadLocalMap,这样可以保证每个线程对应一个独立的 Looper 实 例,进而保证 myLooper() 可以获得线程独有的Looper 彩蛋:一个 App 拥有几个 Looper 实例?几个 ThreadLocal 实例?几 个 MessageQueue 实 例 ? 几 个 Message 实 例 ? 几 个 Handler 实 例
一个线程只有一个 Looper 实例 一个 Looper 实例只对应着一个 MessageQueue 实例 一个 MessageQueue 实例可对应多个 Message 实 例 ,其从 Message 静态池里获取,存在 50 的上限 一个线程可以拥有多个 Handler 实例,其Handler 只是发送和执行 任 务 逻 辑的入口和出口 ThreadLocal 实例是静态的,整个进程共用一个实例。每个 Looper 存放的 ThreadLocalMap 均弱引用它作 为 key
首 先要明确并非不是用来切换线程的,只是为了让每个线程方便程获取自己的 Looper 实例,见 Looper#myLooper()后续可供 Handler 初始化时指定其所属的 Looper 线程 也可用来线程判断自己是否是主线程
区别: Main Looper 不可 quit 主线程需要不断读取系统消息和用书输入,是进程的入口,只可被系统直接终止。进而其 Looper 在创建 的 时 候 设置了不可 quit 的志,而其他线程的 Looper 则可以也必须手动 quit Main Looper 实例 还被静 态缓存 为了 便于每 个线程 获得主 线程 Looper 实例 ,见 Looper#getMainLooper(),Main Looper 实例 还 作 为 sMainLooper 属性缓存到了 Looper 类中。
相同点: 都是通过 Looper#prepare() 间接调用 Looper 构造函数创建的实例 都被静态实例 ThreadLocal 管理,方便每个线程获取自己的 Looper 实例 彩蛋:主线程为什么不用初始化 Looper?
App 的 入 口 并 非 MainActivity, 也 不 是 Application, 而 是 ActivityThread。其 为 了 Application、ContentProvider、Activity 等组 件的运 行,必 须事先 启动不 停接受 输入的 Looper 机制 ,所以 在main()执 行 的最后将调用 prepareMainLooper() 创建 Looper 并调用 loop() 轮循。不需要我们调用,也不可能有我们调用。可以说如果主线程没有创建 Looper 的话,我们的组件也不可能运行得到!
Handler 创 建的 时候指 定了其 所属线 程的 Looper,进 而持有 了 Looper 独有 的 MessageQueue Looper# loop() 会持 续读取 MessageQueue 中合 适的 Message,没 有 Message 的时 候进入 等待当 向 Handler 发 送 Message 或 Runnable 后 , 会 向 持 有 的 MessageQueue 中 插 入 Message ,Message 抵 达并 满足条 件后会 唤醒 MessageQueue 所属 的线程 ,并将 Message 返回 给 Looper Looper 接 着 回 调 Message 所 指 向 的 Handler Callback 或 Runnable,达 到 线 程 切 换 的 目 的简 言之 ,向 Handler 发送 Message 其实 是向 Handler 所属 线程的 独有 MessageQueue 插入 Message。而线 程独有 的Looper 又会 持 续读取该 MessageQueue。所以向其他线程的 Handler 发送完 Message,该线程的 Looper 将自动响应。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。