在 Android 中,Handler
是一种用于在不同线程之间通信和处理消息的机制。
它通常与 Looper
一起使用
1. Handler
基本概念
Handler
类允许你将任务(如消息或可运行的代码块)发送到特定的 消息队列(Message Queue)中,然后在相应的线程中处理它们。每个线程都有自己的消息队列,但 Android 中最常用的是主线程的消息队列。
,用于确保任务在特定线程(如主线程)中执行。Handler
是 Android 中执行并发任务、更新 UI 和处理消息传递的重要工具。
1.1 主线程和消息队列
Android 的主线程(UI线程)有一个与之关联的消息队列,任何要在主线程中执行的任务(例如 UI 更新)都可以通过 Handler
发送到该队列,Handler
会将这些任务分发到主线程的消息队列中。然后,主线程的消息循环会逐个处理这些任务。
2. 如何使用 Handler
2.1 创建 Handler
Handler
可以通过以下几种方式来创建:
- 通过默认的
Handler
:在主线程中创建Handler
,它会默认使用主线程的Looper
。 - 通过指定
Looper
:如果在子线程中创建Handler
,你需要手动传入该线程的Looper
。
2.2 在主线程中使用 Handler
在主线程中创建 Handler
很简单,因为主线程已经有一个默认的 Looper
。
// 在主线程中创建 Handler
Handler handler = new Handler(Looper.getMainLooper());
// 向主线程发送消息
handler.post(new Runnable() {
@Override
public void run() {
// 在主线程执行任务,例如更新 UI
textView.setText(“Hello from Handler!”);
}
});
2.3 在子线程中使用 Handler
如果你在子线程中需要使用 Handler
,你必须确保该子线程已经有一个 Looper
。如果该子线程没有 Looper
,你可以手动创建它。
// 创建一个新的子线程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// 为该线程创建 Looper
Looper.prepare(); // 准备该线程的 Looper
// 创建 Handler 与当前线程的 Looper 关联
Handler handler = new Handler();
// 向该线程发送消息
handler.post(new Runnable() {
@Override
public void run() {
// 在子线程中执行任务
Log.d(“Handler”, “Task executed in background thread”);
}
});
// 启动 Looper,开始处理消息队列
Looper.loop();
}
});
thread.start();
3. Handler
的常用方法
post(Runnable)
: 将 Runnable
任务添加到消息队列,并在适当的线程中执行。最常用的方法之一。
handler.post(new Runnable() {
@Override
public void run() {
// 在主线程中执行的任务
Log.d(“Handler”, “Task is executed”);
}
});
sendMessage(Message)
: 发送 Message
到消息队列,Message
会在之后的某个时刻由 Handler
处理。
Message msg = handler.obtainMessage();
msg.what = 1; // 消息标识
handler.sendMessage(msg);
sendEmptyMessage(int)
: 发送一个没有数据的消息,通常用于传递简单的消息标识。
handler.sendEmptyMessage(1); // 发送标识为 1 的空消息
sendMessageDelayed(Message, long)
: 延迟发送消息,long
参数表示延迟时间(毫秒)。
handler.sendMessageDelayed(message, 1000); // 延迟1秒发送消息
removeCallbacks(Runnable)
: 移除消息队列中的某个 Runnable
,如果该 Runnable
尚未被执行。
handler.removeCallbacks(runnable); // 移除待执行的 Runnable
obtainMessage()
: 获取一个空的 Message
对象,并可以向其中添加数据。
Message msg = handler.obtainMessage();
msg.obj = “Data”; // 向消息中添加数据
handler.sendMessage(msg); // 发送消息
4. 消息的处理
Handler
通过处理消息来实现任务调度和执行。每个 Message
都有一个标识符(what
),可以用来区分不同类型的任务。
你可以通过 Handler
的 handleMessage()
方法来处理接收到的消息。默认情况下,Handler
通过消息队列接收并处理消息。
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
// 处理消息
Log.d(“Handler”, “Received message with ‘what’ = 1”);
break;
default:
break;
}
}
};
你也可以使用 obtainMessage()
方法获取一个带有额外数据的消息。
Message msg = handler.obtainMessage();
msg.what = 1;
msg.obj = “Data”; // 可以传递任何对象
handler.sendMessage(msg);
5. Handler
和 UI 更新
Android 中最常见的使用场景是通过 Handler
在后台线程中执行任务后更新 UI。由于 UI 更新只能在主线程中执行,Handler
使得我们能够轻松地将任务传递回主线程。
5.1 在后台线程执行任务并更新 UI
// 子线程中执行耗时操作
new Thread(new Runnable() {
@Override
public void run() {
// 执行耗时操作
String result = “Operation completed”;
// 更新 UI,需要回到主线程
handler.post(new Runnable() {
@Override
public void run() {
// 在主线程更新 UI
textView.setText(result);
}
});
}
}).start();
6. Handler
和 Looper
每个线程都有一个 Looper
,它负责不断从消息队列中取出消息并执行。主线程已经有了一个默认的 Looper
,所以你可以直接在主线程使用 Handler
。而在子线程中,如果你需要使用 Handler
,必须先准备一个 Looper
,并通过 Looper.loop()
来开始消息处理循环。
7. Handler
与 Looper
的关系
- 主线程:主线程默认有一个
Looper
,通过Looper.getMainLooper()
可以获得主线程的Looper
,所以主线程中的Handler
可以直接使用这个Looper
。 - 子线程:子线程默认没有
Looper
,如果需要在子线程中使用Handler
,你需要先调用Looper.prepare()
来创建一个Looper
,然后通过Looper.loop()
来启动消息循环。
总结:
Handler
是 Android 中用于跨线程通信和任务调度的工具。- 它可以将任务(
Runnable
或Message
)发送到消息队列,并由相应的线程(通常是主线程)处理。 - 在主线程中,你可以直接创建
Handler
;在子线程中,你需要手动创建Looper
。 - UI 更新 必须在主线程中执行,而
Handler
提供了一种安全的方式来从后台线程返回并更新 UI。