由于Android采用的是单线程模式,开发者无法在子线程中更新 UI,所以系统给我提供了 Handler 这个类来实现 UI 更新问题。本贴主要说明 Handler 的工作流程。
1. Handler 的作用
在Android为了保障线程安全,规定只能由主线程来更新UI信息。而在实际开发中,会经常遇到多个子线程都去操作UI信息的情况,那么就会导致UI线程不安全。这时,我们就需要借助 Handler 作为媒介,让 Handler 通知主线程按顺序一个个去更新UI,避免UI线程不安全。
那么,子线程要更新UI的信息时,我们就需要将要更新的消息传递到 UI
主线程中,再由主线程完成更新,从而实现工作线程对UI
的更新处理,最终完成异步消息的处理(如图1所示)。
图1 - 消息传递流程
2. Handler 相关概念解释
主要涉及的有:处理器(Handler)、消息(Message)、消息队列(Message Queue)、循环器(Looper)。
概念 | 定义 | 作用 | 备注 |
主线程 (Main Thread) | 当应用第一次启动时, 就会开启一条主线程。 | 处理与UI相关的事件 | 主线程 ↑ 通讯媒介:Handler ↓ 子线程 |
子线程 | 人为手动开启的 | 执行耗时的操作 (如,网络请求等) | |
消息 (Message) | 线程间通讯的数据单元 (即Handler接受/处理的对象) | 存储需要操作的信息 | |
消息队列 (Message Queue) | 一种数据结构 (队:先进先出) | 存储Handler发来的消息 (Message) | |
处理者 (Handler) | ◆ 主线程与子线程的通讯媒介; ◆ 线程消息的处理者。 | ◆ 添加消息(Message)到消息队列(Message Queue); ◆ 处理由循环器(Looper)分配过来的消息(Message)。 | |
循环器 (Looper) | 消息队列(Message Queue)与 Handler的通讯媒介 | 消息循环即: ◆ 消息获取:循环取出消息队列(Message Queue)中的消息(Message); ◆ 消息分发:将取出的消息(Message)发送给对应的处理者(Handler)。 |
3. 工作原理及流程
Handler 机制流程主要包含4个步骤:
① 异步通讯;
② 消息发送;
③ 消息循环;
④ 消息处理。
详情如下表所示:
步骤 | 具体描述 | 备注 |
---|---|---|
① 异步通讯 | 在主线程中创建: ◆ 处理器对象(Looper) ◆ 消息队列对象(Message Queue) ◆ Handler对象 | ◆ Looper、Message Queue均属于主线程; ◆ 创建完Message Queue后,Looper自动进行消息循环; ◆ 此时,Handler自动绑定到主线程的Looper和Message Queue。 |
② 消息发送 | 子线程通过Handler发送消息消息(Message)到消息队列(Message Queue)中。 | 消息内容 = 子线程对UI的操作 |
③ 消息循环 | ◆ 消息出队:Looper从消息队列(Message Queue)中循环取出消息(Message); ◆ 消息分发:Looper将取出的消息(Message)分发给消息的处理者(Handler)。 | 在消息循环过程中,如果消息队列为空,则自动阻塞。 |
④ 消息处理 | ◆ 处理者(Handler)接受到处理器(Looper)发送过来的消息(Message); ◆ 处理者(Handler)根据消息(Message)进行处理。 |
工作流图(如图2所示):
图2 - Handler 机制工作流图
4. 总结
最后需要注意几点:
线程(Thread)、循环器(Looper)、处理器(Handler)之间的关系如下:
- 一个线程(Thread)只能绑定一个循环器(Looper);但一个Thread可以有多个处理器(Handler)。
- 一个循环器(Looper)可绑定多个处理器(Handler)。
- 一个处理器(Handler)只能绑定一个循环器(Looper)。
图3 - Thread、Looper、Handler 之间的关系