Android后台线程和UI线程通讯实例
作者:冰冻鱼 时间:2023-04-20 23:01:19
本节向你展示如何在任务中发送数据给UI线程里的对象,这个特性允许你在后台线程工作,完了在UI线程展示结果。
在UI线程定义一个Handler
Handler是Android系统线程管理框架里的一部分。一个Handler对象接收消息,并且运行代码来处理消息。正常情况下,你为新线程创建Handler,但你也可以为已有的线程创建一个Handler.当你连接Handler到UI线程时,处理消息的代码会在UI线程上运行.
在创建线程池的类的构造器里实例化Handler对象,保存在全局变量里。用Handler(Looper)方法实例化,连接到UI线程,构造方法使用Looper对象,也是Android系统线程管理框架里的一部分.Looper类有一个静态方法getMainLooper()可以获取UI线程的Looper对象。如:
private PhotoManager() {
...
// Defines a Handler object that's attached to the UI thread
mHandler = new Handler(Looper.getMainLooper()) {
...
在Handler里,覆盖handleMessage()。Android系统会在Handler管理的线程收到新消息时,调用该方法。一个指定线程的所有Handler对象都会收到相同的消息。
/*
* handleMessage() defines the operations to perform when
* the Handler receives a new Message to process.
*/
@Override
public void handleMessage(Message inputMessage) {
// Gets the image task from the incoming Message object.
PhotoTask photoTask = (PhotoTask) inputMessage.obj;
...
}
...
}
}
从任务里移动数据到UI线程
要从后台线程的任务里移动数据到UI线程的对象,先保存引用到数据和任务对象的UI对象里,接下来把任务对象和状态码传给Handler对象。在这个对象里,发送一个包含状态 和任务对象的消息给Handler.因为Handler在UI线程上运行,它可以移动数据给UI对象。
在任务对象里存储数据
如,这是一个Runnable,运行在后台线程,它解析Bitmap,并保存到它的父对象。Runnable同时保存状态码DECODE_STATE_COMPLETED。
// A class that decodes photo files into Bitmaps
class PhotoDecodeRunnable implements Runnable {
...
PhotoDecodeRunnable(PhotoTask downloadTask) {
mPhotoTask = downloadTask;
}
...
// Gets the downloaded byte array
byte[] imageBuffer = mPhotoTask.getByteBuffer();
...
// Runs the code for this task
public void run() {
...
// Tries to decode the image buffer
returnBitmap = BitmapFactory.decodeByteArray(
imageBuffer,
0,
imageBuffer.length,
bitmapOptions
);
...
// Sets the ImageView Bitmap
mPhotoTask.setImage(returnBitmap);
// Reports a status of "completed"
mPhotoTask.handleDecodeState(DECODE_STATE_COMPLETED);
...
}
...
}
...
PhotoTask还包含一个ImageView引用,用来显示Bitmap.尽管引用Bitmap和ImageView是在同一个对象里,但因为不是在UI线程,你不能直接让ImageView显示Bitmap.
沿对象层次逐级发送状态
PhotoTask持有解码的数据和显示数据的View对象的引用,它从PhotoDecodeRunnable接收到状态码,并且沿着线程池里引用的对象和Handler实例传送。
public class PhotoTask {
...
// Gets a handle to the object that creates the thread pools
sPhotoManager = PhotoManager.getInstance();
...
public void handleDecodeState(int state) {
int outState;
// Converts the decode state to the overall state.
switch(state) {
case PhotoDecodeRunnable.DECODE_STATE_COMPLETED:
outState = PhotoManager.TASK_COMPLETE;
break;
...
}
...
// Calls the generalized state method
handleState(outState);
}
...
// Passes the state to PhotoManager
void handleState(int state) {
/*
* Passes a handle to this task and the
* current state to the class that created
* the thread pools
*/
sPhotoManager.handleState(this, state);
}
...
}
移动数据到UI
PhotoManager从PhotoTask对象接收到状态码和PhotoTask对象的句柄。因为状态是TASK_COMPLETE,创建一个包含状态和任务对象的Message,发送给Handler。
public class PhotoManager {
...
// Handle status messages from tasks
public void handleState(PhotoTask photoTask, int state) {
switch (state) {
...
// The task finished downloading and decoding the image
case TASK_COMPLETE:
/*
* Creates a message for the Handler
* with the state and the task object
*/
Message completeMessage =
mHandler.obtainMessage(state, photoTask);
completeMessage.sendToTarget();
break;
...
}
...
}
最终,Handler.handleMessage()为每个进来的Message检查状态码。如果状态码是TASK_COMPLETE,任务就是完成了,Message里的PhotoTask对象包含Bitmap和ImageView.因为Handler.handleMessage()运行在UI线程,它可以安全地为ImageView设置Bitmap.
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Java实现并查集示例详解
![](https://img.aspxhome.com/file/2023/1/116181_0s.png)
浅谈Android开发中项目的文件结构及规范化部署建议
Android中把bitmap存成BMP格式图片的方法
android SDk中常用的java包介绍
Java获取中文拼音、中文首字母缩写和中文首字母的示例
简单讲解java中throws与throw的区别
Java 并发编程之线程挂起、恢复与终止
![](https://img.aspxhome.com/file/2023/9/94209_0s.png)
Java分布式学习之Kafka消息队列
![](https://img.aspxhome.com/file/2023/5/113505_0s.png)
详解Java 信号量Semaphore
![](https://img.aspxhome.com/file/2023/7/69927_0s.png)
Java数据结构之队列(动力节点Java学院整理)
![](https://img.aspxhome.com/file/2023/6/65746_0s.png)
Android键盘输入语言设置默认打开myanmar缅甸语的步骤
基于java构造方法Vector创建对象源码分析
![](https://img.aspxhome.com/file/2023/3/60043_0s.png)
Android实现简单的照相功能
Android自定义WaveProgressView实现水波纹加载需求
![](https://img.aspxhome.com/file/2023/9/137729_0s.gif)
C++ 继承,虚继承(内存结构)详解
![](https://img.aspxhome.com/file/2023/8/120808_0s.png)
java原生序列化和Kryo序列化性能实例对比分析
WPF Slider滑动条的颜色修改方法
![](https://img.aspxhome.com/file/2023/7/81147_0s.png)
Java中equalsIgnoreCase()方法的使用
C#开发中的垃圾回收机制简析
![](https://img.aspxhome.com/file/2023/5/116505_0s.png)
SpringBoot2整合Redis实现读写操作
![](https://img.aspxhome.com/file/2023/5/105925_0s.png)