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();
}
}到此这篇关于android handler 的用法详解的文章就介绍到这了,更多相关android handler 内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论