Handler: 主线程如何通知子线程

本文深入探讨了在Android应用开发中,如何通过HandlerThread与Handler配合使用,实现主线程与子线程之间的高效通信与任务分发。详细解释了在子线程中如何安全地向主线程发送消息,更新UI,以及避免常见的并发错误。通过实例代码演示了如何创建、启动子线程,以及如何在子线程中使用Message传递数据并由主线程处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Handler: 主线程如何通知子线程
分类: Android 2012-01-02 10:48 4772人阅读 评论(18) 收藏 举报
在 android 中,不可以在子线程中更新 UI 的操作,否则会报错或者异常信息。

在这种情况下,我们会使用 Handler(在 UI 线程创建该对象) 接收子线程的消息更新 UI.

可以看出,这是子线程通知主线程,而主线程没有直接通知子线程,那麽我们如何做到这一点?这样有什么好处?
好处,很明显。主线程中如果有些耗时的操作,我们可以让子线程去做,这时,主线程就可以通知子线程了!

实现这种操作的方式有很多,今天主要想说说 HandlerThread 与 Handler 的配合使用方法。

在主线程中,可以创建 HandlerThread 对象:
HandlerThread mHandlerThread = new HandlerThread("sub_thread");
mHandlerThread.start();


这样,就开启了一个子线程,该线程的名字就是 sub_thread.

然后,我们实现一个继承自 Handler 的 MyHandler 类:
class MyHandler extends Handler {

public MyHandler() {
super();
}

public MyHandler(Looper looper) {
super(looper);
}

@Override
public void handleMessage(Message msg) {
// super.handleMessage(msg);
if(msg.what == MSG_WHAT) {
Bundle bundle = msg.getData();
String info = bundle.getString("main");
Log.d("mark", "我接受任务:" + info);
}
}
}

最后,使用 Message 来传递消息,MyHandler 会根据情况处理 Message.

完整代码:
package mark.zhang;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

public class HandlerThreadActivity extends Activity {

private static final int MSG_WHAT = 1;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// 创建对象,并启动该线程
HandlerThread mHandlerThread = new HandlerThread("sub_thread");
mHandlerThread.start();
// 获取 Looper 对象
MyHandler mHandler = new MyHandler(mHandlerThread.getLooper());
// 创建 Bundle 对象,传递数据
Bundle bundle = new Bundle();
bundle.putString("main", "我这边事情太多,麻烦你帮忙处理一下!");
// 发送消息
Message msg = new Message();
msg.what = MSG_WHAT;
msg.setData(bundle);
msg.setTarget(mHandler);
msg.sendToTarget();

Log.d("mark", "UI----" + "threadName: " + Thread.currentThread().getName() + ",threadId: " + Thread.currentThread().getId());
}

/**
* 该Handler调用 handleMessage方法运行在子线程
*
* @author mark
*/
class MyHandler extends Handler {

public MyHandler() {
super();
}

/* 这个构造方法必须有 */
public MyHandler(Looper looper) {
super(looper);
}

@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_WHAT) {
Bundle bundle = msg.getData();
// 接收消息
String info = bundle.getString("main");
Log.d("mark", "handleMessage---" + "threadName: " + Thread.currentThread().getName() + ",threadId: " + Thread.currentThread().getId());
Log.d("mark", "我接受任务:" + info);
}
}
}
}

这里,我们思考一个问题,代码:
// 获取 Looper 对象
MyHandler mHandler = new MyHandler(mHandlerThread.getLooper());

获取 Looper 对象,使用的是 HandlerThread 对象的 getLooper 对象。为什么不直接这样:
// 获取 Looper 对象
MyHandler mHandler = new MyHandler(getMainLooper());

如果这样做的话,打印信息如下:
D/mark (21852): UI----threadName: main,threadId: 1
D/mark (21852): handleMessage---threadName: main,threadId: 1
D/mark (21852): 我接受任务:我这边事情太多,麻烦你帮忙处理一下!

可见,此时的 handleMessage 是在主线程中运行的。每个主线程默认有一个 Looper,也就是说在主线程中,下面代码是等效的:
MyHandler mHandler = new MyHandler(getMainLooper());
MyHandler mHandler = new MyHandler();

但是子线程需要手动获取如:
MyHandler mHandler = new MyHandler(mHandlerThread.getLooper());

实现主线程、子线程双向通信可以在各自的线程中分别是用 Handler 来传递信息和处理消息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值