Android 中 Handler 的用法详解
Handler 是 Android 中用于线程间通信的重要机制,主要用于在不同线程之间发送和处理消息。以下是 Handler 的全面用法指南:
一、Handler 的基本原理
Handler 基于消息队列(MessageQueue)和循环器(Looper)工作,主要组成:
Message:携带数据的消息对象
MessageQueue:消息队列,存储待处理的消息
Looper:消息循环,不断从队列取出消息处理
Handler:发送和处理消息的接口
二、基本用法
1. 创建 Handler(主线程)
// 在主线程创建Handler会自动关联主线程的Looper
Handler mainHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
// 处理消息
switch (msg.what) {
case 1:
String text = (String) msg.obj;
textView.setText(text);
break;
}
}
};
2. 发送消息
// 发送空消息
handler.sendEmptyMessage(1);
// 发送带what的消息
Message msg = handler.obtainMessage();
msg.what = 2;
msg.obj = "Hello Handler";
handler.sendMessage(msg);
// 延迟发送
handler.sendEmptyMessageDelayed(1, 1000); // 1秒后发送
handler.sendMessageDelayed(msg, 2000); // 2秒后发送
3. 在子线程使用 Handler
new Thread(() -> {
// 为当前线程创建Looper
Looper.prepare();
Handler threadHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 处理子线程消息
}
};
// 开始消息循环
Looper.loop();
}).start();
三、Handler 的常见使用场景
1. 更新 UI
new Thread(() -> {
// 模拟耗时操作
try {
Thread.sleep(1000);
// 通过Handler发送消息到主线程更新UI
Message msg = mainHandler.obtainMessage();
msg.what = 1;
msg.obj = "更新后的文本";
mainHandler.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
2. 定时任务
// 延迟执行
handler.postDelayed(() -> {
Toast.makeText(this, "5秒后执行", Toast.LENGTH_SHORT).show();
}, 5000);
// 循环执行
final Runnable runnable = new Runnable() {
@Override
public void run() {
// 执行任务
Log.d("Handler", "每隔1秒执行");
// 再次post实现循环
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(runnable, 1000);
// 取消定时任务
handler.removeCallbacks(runnable);
3. 线程间通信
// 工作线程
class WorkerThread extends Thread {
public Handler workerHandler;
@Override
public void run() {
Looper.prepare();
workerHandler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(Message msg) {
// 处理来自主线程的消息
String task = (String) msg.obj;
Log.d("WorkerThread", "执行任务: " + task);
// 可以回传结果给主线程
Message resultMsg = mainHandler.obtainMessage();
resultMsg.what = 2;
resultMsg.obj = task + " 完成";
mainHandler.sendMessage(resultMsg);
}
};
Looper.loop();
}
}
// 主线程发送任务给工作线程
WorkerThread worker = new WorkerThread();
worker.start();
// 等待workerHandler初始化
new Handler().postDelayed(() -> {
if (worker.workerHandler != null) {
Message msg = worker.workerHandler.obtainMessage();
msg.obj = "下载文件";
worker.workerHandler.sendMessage(msg);
}
}, 1000);
四、高级用法
1. 使用 HandlerThread
// 创建HandlerThread
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
// 获取HandlerThread的Looper创建Handler
Handler threadHandler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
// 在后台线程处理消息
}
};
// 发送消息
threadHandler.post(() -> {
// 在HandlerThread中执行
});
// 退出时释放资源
handlerThread.quitSafely();
2. 避免内存泄漏
// 使用静态内部类+弱引用
private static class SafeHandler extends Handler {
private final WeakReference<Activity> activityRef;
public SafeHandler(Activity activity) {
super(Looper.getMainLooper());
this.activityRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
Activity activity = activityRef.get();
if (activity != null && !activity.isFinishing()) {
// 安全处理消息
}
}
}
// 在Activity中使用
private SafeHandler safeHandler = new SafeHandler(this);
3. 使用 Message 的优化
// 复用Message对象(推荐)
Message msg = handler.obtainMessage(WHAT_ARG, obj);
handler.sendMessage(msg);
// 设置回调代替继承Handler
handler.sendMessage(Message.obtain(handler, () -> {
// 回调处理
}));
五、注意事项
线程安全:Handler 与创建它的线程绑定,不能跨线程直接使用
内存泄漏:非静态 Handler 内部类会持有外部类引用,Activity 销毁时要移除回调
Looper 准备:子线程使用 Handler 必须先调用 Looper.prepare()
消息堆积:避免发送过多消息导致消息队列堵塞
及时清理:在 onDestroy() 中移除所有回调
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null);
if (handlerThread != null) {
handlerThread.quitSafely();
}
}
原文链接:https://blog.csdn.net/qq_39460057/article/details/146875072