本节向你展示如何在任务中发送数据给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; ... } ... }