1.1 Handler
1.1.1 Handler
1. Handler 组件
- handler:负责接收和处理消息,每个 handler 会关联一个线程,并关联到该线程的消息队列
- message:handler 传递的消息对象,在目标线程中处理
- looper:循环读取消息队列中的 message,每个线程有且仅有一个 looper
2. 源码
1. Handler 的源码结构:
Handler 类通过持有 Looper 和 MessageQueue 实现消息的发送和处理
public class Handler {
private Looper mLooper;
private MessageQueue mQueue;
public Handler() {
this(Looper.myLooper());
}
public Handler(Looper looper) {
mLooper = looper;
mQueue = looper.getQueue();
}
public void handleMessage(Message msg) {
// 处理消息的逻辑
}
public final boolean sendMessage(Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
if (msg.target == null) {
msg.target = this;
}
return mQueue.enqueueMessage(msg, delayMillis);
}
}
2. Message 的源码结构
Message 对象 封装要传递的消息,目标 handler、消息类型
public final class Message {
public int what;
public Object obj;
public Handler target;
// 其他成员变量
public static Message obtain() {
return new Message();
}
}
3. Looper 的源码结构
Looper 在 loop 方法中不断从 MessageQueue 中取出消息,并通过 Handler 的 dispatchMessage 方法将消息分发给对应的 Handler 处理
public final class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
MessageQueue mQueue;
private Looper() {
mQueue = new MessageQueue();
}
public static void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
public static Looper myLooper() {
return sThreadLocal.get();
}
public static void loop() {
Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next();
if (msg == null) {
return;
}
msg.target.dispatchMessage(msg);
msg.recycle();
}
}
public MessageQueue getQueue() {
return mQueue;
}
}
3. Handler 的使用
- 创建 Handler 对象:Handler 会与当前线程的 Looper 关联
Handler handler = new Handler();
2. 发送消息:使用 Handler 的 sendMessage () 或 sendMessageDelayed () 方法发送消息到消息队列中,供处理线程处理
Message msg = handler.obtainMessage();
msg.what = 1; // 设置消息类型
msg.obj = "Hello"; // 设置消息数据
handler.sendMessage(msg); // 发送消息
3. 处理消息:在 Handler 中重写 handleMessage () 方法,用于处理接收到的消息,在 handleMessage () 方法中,可以根据不同的消息类型进行逻辑处理。通过 msg.obj 可以获取消息携带的数据
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
String data = (String) msg.obj; // 获取消息数据
// 处理消息逻辑
break;
// 其他消息类型的处理
}
}
4. 在特定线程中创建 Handler 对象:有时需要在特定的线程中创建 Handler 对象,可以通过 Looper 来实现。例如,在后台线程中创建 Handler 对象:
Handler handler;
Thread thread = new Thread(new Runnable() {
public void run() {
Looper.prepare();
handler = new Handler() {
public void handleMessage(Message msg) {
// 处理消息逻辑
}
};
Looper.loop();
}
});
thread.start();
4. Handler 应用:
- 线程间通信:通过 handler,可以将消息发送到目标线程的消息队列中,在目标线程中处理消息
UI 线程更新:
Handler handler = new Handler();
handler.post(new Runnable() {
public void run() {
// 在UI线程中执行任务,用于更新UI
// 更新UI等操作
}
});
- 异步任务:后台线程中处理任务,再将结果发送到 UI 线程,如网络请求、文件读写场景
异步加载数据:
// 在后台线程中加载数据
Thread thread = new Thread(new Runnable() {
public void run() {
// 执行耗时操作,如网络请求或数据库查询
// 加载完成后,发送消息通知主线程
Message message = handler.obtainMessage();
message.what = LOAD_COMPLETE;
message.obj = loadedData;
handler.sendMessage(message);
}
});
thread.start();
// 主线程中处理消息
Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == LOAD_COMPLETE) {
// 处理加载完成的数据
Object data = msg.obj;
// 更新UI等操作
}
}
};
- 延迟任务:通过 handler 的 postDelayed 方法延迟执行任务
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// 延时操作,例如延时2秒后执行某个任务
// 更新UI等操作
}
}, 2000); // 2000毫秒的延迟