在 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);
}
}
}
}
这里,我们思考一个问题,代码:
-
- MyHandler mHandler = new MyHandler(mHandlerThread.getLooper());
获取 Looper 对象,使用的是 HandlerThread 对象的 getLooper 对象。为什么不直接这样:
-
- 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 来传递信息和处理消息。
分享到:
相关推荐
Handler消息传递详解,子线程到子线程,主线程到子线程,子线程到主线程 三种消息,Looper,Handler工作机制详解 https://blog.csdn.net/shoneworn/article/details/80447651
当主线程的`Handler`接收到子线程发送的消息后,会调用`handleMessage(Message msg)`方法进行处理,这里可以更新UI或者执行其他需要在主线程进行的操作。 6. **示例代码**: ```java // 主线程的Handler class ...
- **Handler**:在主线程中创建一个Handler对象,并关联到Looper,然后子线程可以通过发送Message对象到Handler,由主线程处理。这种方式适用于异步任务的结果返回到UI线程更新界面。 - **Runnable**:可以直接...
本文将深入探讨如何使用Handler机制实现主线程与子线程,以及HandlerThread之间的双向通信。 首先,理解Android的线程模型至关重要。主线程,也称为UI线程,负责处理所有的用户交互和更新UI。由于Android系统对主线...
- Handler: 主线程中的Handler对象可以接收并处理由其他线程(通常是子线程)通过Looper和Message发送的消息。Message对象可以携带数据,这样子线程就可以将数据封装在Message中,然后通过Handler发送到主线程。 -...
3. 如果需要在子线程中更新UI,必须通过Handler、runOnUiThread或使用Android提供的AsyncTask等机制,将任务回调到主线程执行。 在给定的代码示例中,可以看到以下几个关键点: 1. 使用委托(Delegate)来定义多个...
5. **发送消息**:在主线程中,通过之前创建的主线程Handler使用`sendMessage()`或`post()`方法向子线程的Handler发送Message。 6. **处理消息**:子线程的Handler会在其Looper的消息循环中接收到主线程发送的消息...
这个概念可能是指在子线程中创建的Handler实例,用于与主线程的Handler进行通信。通常,我们在子线程中创建一个Handler,然后通过Looper.prepare()和Looper.loop()来启动一个消息循环,使子线程也能接收和处理消息...
Handler的定义:主要接受子线程发送的数据, 并用此数据配合主线程更新UI.解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个...
1. 在子线程中,创建一个Handler实例,并将其与主线程的Looper关联。这通常通过在子线程中调用Looper.prepare()和Looper.loop()完成。 2. 创建一个Message对象,并设置其what属性来标识消息类型,或者通过Bundle传递...
2. 使用Handler:为了在子线程中更新UI,可以创建一个与主线程关联的Handler实例。在子线程中,创建Message,设置其目标为该Handler,然后调用sendMessage()方法将Message放入主线程的MessageQueue。主线程的Looper...
这个demo介绍了通过Handler在线程之间传递消息,demo中一个三个线程,主线程,发送消息的分线程,接收消息的分线程。发送消息的分线程会通知主线程更改标签文字,同时会通知接收消息的分线程更改进度条的进度。
总结来说,Android主线程通过`Handler`和`Looper`机制可以有效地与多个工作线程进行通信。这种模式不仅避免了直接操作UI的潜在风险,还确保了UI更新的同步性,是Android异步编程的重要工具。在实际项目中,还可以...
Android系统主要分为两个线程:主线程(UI线程)和工作线程。主线程负责处理用户界面的绘制和事件响应,而工作线程用于执行耗时操作,避免阻塞UI。由于Android系统的安全限制,直接在工作线程中更新UI是不允许的,这...
因此,要在子线程中更新主线程的控件,你需要利用Android的消息传递机制,主要是通过`Message`和`Handler`来实现。 首先,理解`Handler`和`Looper`的角色。`Handler`是消息处理器,负责接收和处理来自其他线程的...
通过Handler、Looper和Message三者之间的协同工作,开发者可以在主线程与子线程之间进行安全的数据传递和任务调度。 首先,我们来理解Handler的基本概念。Handler是Android中的一个类,用于发送和处理消息。它的...
子线程通过Handler、Looper和Message机制来通知主线程进行UI更新。具体来说,子线程会创建一个Message对象,并通过Handler将消息发送到主线程的消息队列中。主线程的Looper会不断地从消息队列中取出消息,并在主线程...
为了在主线程和子线程之间进行有效的通信,Android提供了消息传递机制,主要通过Handler、Looper和Message三个关键组件来实现。 首先,我们来看如何从主线程发送消息到子线程。在给定的代码示例中,创建了一个名为`...
在Android应用开发中,Handler是用于处理主线程与子线程之间通信的重要工具。它允许开发者在后台线程执行耗时操作(如计算斐波那契数列),然后通过Message对象将结果回调到主线程更新UI。在这个场景中,我们讨论的...
在Android开发中,线程和线程池是处理异步任务的重要工具,而Handler则是用于在主线程和子线程之间通信的关键组件。本篇文章将深入探讨这些概念,以及它们在实际应用中的用法。 首先,让我们理解什么是线程。线程是...