在 Android 中,Handler
是用于在不同线程之间传递消息和执行任务的机制,尤其是常用于主线程(UI线程)和工作线程之间的通信。它与 MessageQueue
和 Looper
紧密协作,以实现异步处理和更新 UI 的功能。
1、核心组件
- Message:是用来传递数据的基本单位。
每个
Message
包含:what: 一个整型标识符,用于标识消息的类型。
arg1、arg2: 可选的整型参数,用来传递数据。
obj: 一个
Object
类型的字段,可以用来传递复杂的数据。target: 指定处理消息的
Handler
,通常由sendMessage
或sendMessageAtTime
自动设置。
- MessageQueue:表示是一个消息队列,用于存储待处理的消息。它通常与一个
Looper
绑定,每个线程可以有一个MessageQueue
。消息被发送到消息队列中,Looper
会持续从队列中取出消息并分发给相应的Handler
。 - Looper:表示是一个消息循环器,它负责从消息队列中取出消息,并将消息传递给相应的
Handler
进行处理。每个线程通常有一个Looper
,主线程默认有一个Looper
,其他线程需要手动创建和准备Looper
。 - Handler:是用于处理消息的工具。它通常与一个
Looper
关联,用来接收并处理从消息队列中传递过来的消息。
通过
Handler
可以:发送消息到队列。
定时执行任务(通过
postDelayed
或sendMessageAtTime
)。将耗时操作的结果返回到主线程更新 UI。
四者对应的关系:
一个线程只能有一个 Looper,并且对应一个 MessageQueue,MessageQueue 中可以有 n 条消息,并且一个 Looper 可以被 n 多个 Handler 绑定。每个 Handler 都可以向 Looper 发消息并接受消息处理逻辑。
2、工作流程
主线程和工作线程
在 Android 中,主线程(UI线程)负责管理 UI 更新,而耗时操作通常在后台线程中执行。为了更新 UI 或进行线程间的通信,需要通过消息机制来实现。
如图所示线程 A 可以表示工作线程,线程 B 表示 UI 线程。
- 发送消息:
- 消息通常由某个线程(如后台线程)通过
Handler
发送到主线程或其他线程。 - 消息可以包含数据(例如
Message.obj
或arg1
,arg2
),可以通过sendMessage()
或post()
方法发送。 Handler
也可以发送Runnable
对象,这样Runnable
就会被添加到消息队列中,并在适当的时候执行。
- 消息循环:
- 主线程(UI线程)和其他线程的
Looper
会运行一个无限的循环:Looper.loop()
,在这个循环中不断地从消息队列中取出消息,传递给相应的Handler
进行处理。
- 处理消息:
Looper
会从消息队列中取出消息,并交给对应的Handler
处理。每个Handler
都有一个handleMessage()
方法,用来处理它接收到的消息。Handler
还可以通过post()
或sendMessage()
来在其他线程上执行任务。
3、总结
Android 的消息机制通过 MessageQueue
、Looper
和 Handler
实现了线程间的通信,特别是 UI 线程和后台线程之间。它允许我们安全地在后台线程执行耗时操作,并在操作完成后通过消息机制将结果传递回主线程更新 UI。这种机制能够保证 UI 不被阻塞,同时避免线程间的直接交互带来的同步问题。