Handler 是 Android 中的一个类,用于实现线程之间的消息传递和任务调度。它基于消息队列(Message Queue)和消息循环(Message Loop)的机制,允许你在一个线程中创建 Handler 对象,用于发送和处理消息。
以下是 Handler 消息机制的基本原理:
-
消息队列(Message Queue):每个 Handler 对象都关联一个消息队列,用于存储待处理的消息。消息队列采用先进先出(FIFO)的方式,即先发送的消息先被处理。
-
消息循环(Message Loop):每个线程只能有一个消息循环,它负责从消息队列中取出消息,并将其传递给对应的 Handler 进行处理。消息循环以无限循环的方式运行,不断地从消息队列中获取消息并处理,直到消息队列为空或被终止。
-
消息对象(Message):消息对象封装了要处理的信息和相关的数据。它包含一个标识符(what),用于指定消息类型或操作代码,以及可选的附加数据(Bundle 对象)。
-
发送消息:通过 Handler 对象的
sendMessage()
或post()
方法,可以向消息队列发送消息。你可以指定消息类型、延迟时间、附加数据等。 -
处理消息:在 Handler 对象中,你可以重写
handleMessage()
方法,用于处理接收到的消息。根据消息的类型或标识符,你可以执行相应的操作。
通过使用 Handler 消息机制,你可以在不同的线程之间进行通信和任务调度。例如,在主线程(UI 线程)中创建一个 Handler 对象,你可以将消息发送到该 Handler,在 UI 线程中处理这些消息以更新用户界面。另外,你还可以在后台线程中创建 Handler 对象,用于执行异步任务并将结果发送回主线程。
这种消息机制使得线程间的通信更加简单和安全,避免了直接操作共享数据带来的并发问题。
Handler 与 Looper 紧密相关,Looper 负责消息队列的循环。当你创建一个 Handler 实例时,它默认与当前线程的 Looper 关联。如果有多个 Handler 实例,它们将共享同一个 Looper。Handler 可以发送消息(Message)和Runnable对象到消息队列中。这些消息和Runnable对象将在 Looper 的循环中按顺序执行。当 Handler 发送消息或Runnable对象时,它们被放入一个消息队列中。每个线程有一个消息队列,用于存储待处理的消息和Runnable对象。Looper 从消息队列中取出消息并执行它们,或者将它们传递给 Handler 的 handleMessage
方法。消息(Message)是一个包含 what、arg1、arg2 和一个可选项 obj(通常是 Bundle)的对象。Runnable 对象是一个实现了 Runnable
接口的对象,可以直接发送到消息队列中执行。同步消息(SYNC)会阻塞消息队列,直到消息处理完成。异步消息(ASYNC)不会阻塞消息队列,消息处理是并发的。Handler 的 handleMessage
方法用于处理接收到的消息。你可以重写 handleMessage
方法来定义如何处理不同类型的消息。Handler 通常用于更新 UI 元素,因为 UI 更新必须在主线程(UI 线程)中执行。它也用于在后台线程和主线程之间传递数据,或者在不同的后台线程之间进行通信。我们使用的时候应该避免在 Handler 中创建无限循环或者长时间运行的任务,这可能会导致应用程序无响应(ANR)。确保在正确的线程中使用 Handler,否则可能会导致线程间通信问题。
与Looper结合使用Handler消息机制的步骤如下:
1. 创建Handler对象和Looper对象:在目标线程中创建一个Looper对象,并将其启动,然后创建一个Handler对象与该Looper相关联。
Looper.prepare(); // 创建并启动Looper
Handler handler = new Handler();
Looper.loop(); // 进入Looper的消息循环
2. 发送消息或Runnable对象:在源线程中,通过Handler对象发送消息或Runnable对象到目标线程的消息队列。
handler.sendEmptyMessage(MSG_WHAT); // 发送一个消息
handler.post(runnable); // 发送一个Runnable对象
3. 处理消息:在目标线程中,通过重写Handler的`handleMessage()`方法来处理收到的消息。
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_WHAT:
// 处理消息
break;
// 其他case...
}
}
};
4. 退出消息循环:如果需要退出消息循环,可以调用Looper的`quit()`或`quitSafely()`方法。
looper.quit(); // 退出消息循环
在使用Looper和Handler时,需要注意以下几点:
- 通常情况下,Looper和Handler是在同一线程中使用的,例如在主线程中。但也可以在其他线程中使用,只需在该线程中创建Looper和Handler即可。
- Looper的`loop()`方法会进入一个无限循环,不断从消息队列中取出消息并分发给对应的Handler进行处理。因此,如果不需要继续处理消息,需要手动退出消息循环。
- 在与Looper结合使用时,Handler的构造函数可以接收一个Looper对象作为参数,来关联指定的Looper。例如:`Handler handler = new Handler(myLooper);`
- 如果在子线程中使用Looper和Handler,需要在子线程的`run()`方法中创建Looper并调用`loop()`方法,以确保消息循环在子线程中执行。
总结起来,与Looper结合使用Handler消息机制可以实现在不同线程间进行消息传递和异步处理。通过创建Looper对象和Handler对象,并在目标线程中进入消息循环,可以实现消息的接收和处理。