Android 线程池系列教程(5)与UI线程通信要用Handler
1.This lesson teaches you to
2.You should also read
3.Try it out
In the previous lesson you learned how to start a task on a thread managed by ThreadPoolExecutor. This final lesson shows you how to send data from the task to objects running on the user interface (UI) thread. This feature allows your tasks to do background work and then move the results to UI elements such as bitmaps.
Every app has its own special thread that runs UI objects such as View objects; this thread is called the UI thread. Only objects running on the UI thread have access to other objects on that thread. Because tasks that you run on a thread from a thread pool aren't running on your UI thread, they don't have access to UI objects. To move data from a background thread to the UI thread, use a Handler that's running on the UI thread.
4.Define a Handler on the UI Thread
Handler is part of the Android system's framework for managing threads. A Handler object receives messages and runs code to handle the messages. Normally, you create a Handler for a new thread, but you can also create a Handler that's connected to an existing thread. When you connect a Handler to your UI thread, the code that handles messages runs on the UI thread.
Instantiate the Handler object in the constructor for the class that creates your thread pools, and store the object in a global variable. Connect it to the UI thread by instantiating it with the Handler(Looper)constructor. This constructor uses a Looper object, which is another part of the Android system's thread management framework. When you instantiate a Handler based on a particular Looper instance, theHandler runs on the same thread as the Looper. For example:
private PhotoManager() {
...
// Defines a Handler object that's attached to the UI thread
mHandler = new Handler(Looper.getMainLooper()) {
...
Inside the Handler, override the handleMessage() method. The Android system invokes this method when it receives a new message for a thread it's managing; all of the Handler objects for a particular thread receive the same message. For example:
/*
* 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;
...
}
...
}
}
The next section shows how to tell the Handler to move data.
5.Move Data from a Task to the UI Thread
Handler. In this object, send a Message containing the status and the task object to the Handler. Because Handler is running on the UI thread, it can move the data to the UI object.
5.1Store data in the task object
For example, here's a Runnable, running on a background thread, that decodes a Bitmap and stores it in its parent object PhotoTask. The Runnable also stores the status code 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,
,
imageBuffer.length,
bitmapOptions
);
...
// Sets the ImageView Bitmap
mPhotoTask.setImage(returnBitmap);
// Reports a status of "completed"
mPhotoTask.handleDecodeState(DECODE_STATE_COMPLETED);
...
}
...
}
...
PhotoTask also contains a handle to the ImageView that displays the Bitmap. Even though references to the Bitmap and ImageView are in the same object, you can't assign the Bitmap to the ImageView, because you're not currently running on the UI thread.
Instead, the next step is to send this status to the PhotoTask object.
5.2 Send status up the object hierarchy
PhotoTask is the next higher object in the hierarchy. It maintains references to the decoded data and theView object that will show the data. It receives a status code from PhotoDecodeRunnable and passes it along to the object that maintains thread pools and instantiates 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);
}
...
}
5.3 Move data to the UI
From the PhotoTask object, the PhotoManager object receives a status code and a handle to thePhotoTask object. Because the status is TASK_COMPLETE, creates a Message containing the state and task object and sends it to the 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;
...
}
...
}
Finally, Handler.handleMessage() checks the status code for each incoming Message. If the status code isTASK_COMPLETE, then the task is finished, and the PhotoTask object in the Message contains both aBitmap and an ImageView. Because Handler.handleMessage() is running on the UI thread, it can safely move the Bitmap to the ImageView:
private PhotoManager() {
...
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message inputMessage) {
// Gets the task from the incoming Message object.
PhotoTask photoTask = (PhotoTask) inputMessage.obj;
// Gets the ImageView for this task
PhotoView localView = photoTask.getPhotoView();
...
switch (inputMessage.what) {
...
// The decoding is done
case TASK_COMPLETE:
/*
* Moves the Bitmap from the task
* to the View
*/
localView.setImageBitmap(photoTask.getImage());
break;
...
default:
/*
* Pass along other messages from the UI
*/
super.handleMessage(inputMessage);
}
...
}
...
}
...
}
...
}
Android 线程池系列教程(5)与UI线程通信要用Handler的更多相关文章
- Android 线程池系列教程(3) 创建线程池
Creating a Manager for Multiple Threads 上一课 下一课 1.This lesson teaches you to Define the Thread Pool ...
- Android 线程池系列教程(2)Thread,Runnable是基类及如何写Run方法
Specifying the Code to Run on a Thread 上一课 下一课 1.This lesson teaches you to Define a Class that Im ...
- Android 线程池系列教程(1)目录
Sending Operations to Multiple Threads 1.Dependencies and prerequisites Android 3.0 (API Level 11) o ...
- Android 线程池系列教程(4) 启动线程池中的线程和中止池中线程
Running Code on a Thread Pool Thread 上一课 下一课 1.This lesson teaches you to Run a Runnable on a Thre ...
- 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分
这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...
- 《java.util.concurrent 包源码阅读》11 线程池系列之ThreadPoolExecutor 第一部分
先来看ThreadPoolExecutor的execute方法,这个方法能体现出一个Task被加入到线程池之后都发生了什么: public void execute(Runnable command) ...
- Mysql线程池系列一:什么是线程池和连接池( thread_pool 和 connection_pool)
thread_pool 和 connection_pool 当客户端请求的数据量比较大的时候,使用线程池可以节约大量的系统资源,使得更多的CPU时间和内存可以高效地利用起来.而数据库连接池的使用 ...
- C# 多线程学习系列三之CLR线程池系列之ThreadPool
一.CLR线程池 1.进程和CLR的关系一个进程可以只包含一个CLR,也可以包含多个CLR2.CLR和AppDomain的关系一个CLR可以包含多个AppDomain3.CLR和线程池的关系一个CLR ...
- java线程池系列(1)-ThreadPoolExecutor实现原理
前言 做java开发的,一般都避免不了要面对java线程池技术,像tomcat之类的容器天然就支持多线程. 即使是做偏后端技术,如处理一些消息,执行一些计算任务,也经常需要用到线程池技术. 鉴于线程池 ...
随机推荐
- 白话空间统计之四:P值和Z值(上):零如果
本来今天想要讲讲软件操作的,后来发现好像还有好几个重要的指标没有说,干脆等所有说完在讲操作吧.否则操作出来的结果会发现大量的"不明觉厉". 首先是空间统计里面非常神奇的两个值:P值 ...
- JavaSE----API之集合(Collection、List及其子类、Set及其子类、JDK1.5新特性)
5.集合类 集合类的由来: 对象用于封装特有数据,对象多了须要存储:假设对象的个数不确定.就使用集合容器进行存储. 集合容器由于内部的数据结构不同,有多种详细容器.不断的向上抽取,就形成了集合框架. ...
- LightOJ - 1317 Throwing Balls into the Baskets 期望
题目大意:有N个人,M个篮框.K个回合,每一个回合每一个人能够投一颗球,每一个人的命中率都是同样的P.问K回合后,投中的球的期望数是多少 解题思路:由于每一个人的投篮都是一个独立的事件.互不影响.所以 ...
- Java使用三种不同循环结构对1+2+3+...+100 求和
▷//第一种求法,使用while结构 /** * @author 9527 * @since 19/6/20 */ public class Gaosi { public static void ma ...
- Android ImageLoader 本地缓存
Android ImageLoader 本地缓存 本地缓存 ...
- myeclipse配置hadoop开发环境
1.安装Hadoop开发插件 hadoop安装包contrib/目录下有个插件hadoop-0.20.2-eclipse-plugin.jar,拷贝到myeclipse根目录下/dropins目录下. ...
- 【Linux 内核网络协议栈源码剖析】网络栈主要结构介绍(socket、sock、sk_buff,etc)
原文:http://blog.csdn.net/wenqian1991/article/details/46700177 通过前面的分析,可以发现,网络协议栈中的数据处理,都是基于各类结构体,所有有关 ...
- jsp实现翻页功能
jsp实现翻页功能 要实现翻页功能,只需要设置一个pageIndex即可,然后每次加载页面时通过pageIndex去加载数据就行. 那么我们可以设置一个隐藏的input框,用于传递pageIndex给 ...
- DOM方式解析xml实例2
老样子,javabean实体类: import java.io.*; public class Book implements Serializable { private int id; priva ...
- mac系统下命令编译android ndk项目
1.设置ndk环境变量 2.构造android ndk项目,命令:ndk-build 3.使用ant构造android sdk项目:命令:android update project -p . -n ...