多线程与UI线程间通信

向你展示如何从任务发送数据对象上运行用户界面(UI)线程。该特性允许你的任务做背景的工作结果,然后再到UI元素如位图。

每个应用程序都有自己的特殊的线程运行的UI对象如视图对象; 这个线程称为UI线程。只有在UI线程上运行对象访问其他线程的对象。因为你的任务运行在一个线程从一个线程池不是UI线程上运行,他们没有对UI对象的访问。将数据从一个后台线程到UI线程,使用Handler的UI线程上运行。

在UI线程上定义一个Handler

Handler是Android系统的框架的一部分来管理线程。Handler对象接收消息并运行代码来处理这些消息。正常地,您为了一个新线程创建一个Handler ,但你也能创建一个Handler连接到一个现有的线程。当你连接一个Handler到你的UI线程,处理消息的代码在UI线程上运行。

例子:一个Handler对象类的构造函数中创建你的线程池, 并将对象存储在一个全局变量。它连接到UI线程通过实例化Handler(Looper)构造函数。这个构造函数使用一个Looper对象,这是另一个Android系统的线程管理框架的一部分。当你实例化一个基于特定的Looper实例的Handler对象,Handler 就像

Looper一样运行在相同的线程

代码例子:

private PhotoManager() {
...// Defines a Handler object that's attached to the UI thread
    mHandler = new Handler(Looper.getMainLooper()) {...

里面的Handler,重写了handlerMessage()方法。Android系统调用此方法收到新消息时,线程的管理;所有的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;
            ...
        }...}
}
The next section shows how to tell the Handler to move data.

后台线程与UI线程交换数据

运行在后台的线程任务与UI线程交换数据,首先引用数据和UI对象存储在任务对象。接下来,通过任务对象和一个状态码来实例化的对象处理程序。在这个对象,包含状态和任务对象发送一个消息Handler。因为Handler是在UI线程上运行,它可以将数据移动到UI对象。.

在任务对象存储数据

例如, 这里有一个 Runnable, 运行在一个后台线程, 解码一个PhotoTask位图并将其存储在它的父对象。The 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也包含一个处理ImagVie显示位图。尽管引用同一个对象的bitmap和ImageView,, 你不能分配ImageView的位图, 因为你不是目前在UI线程上运行。

相反,下一步是把这状态发送到PhotoTask对象。

发送状态的对象层次结构

PhotoTask 在层次结构中是下一个更高的对象。它维护引用的解码数据和视图对象将显示数据。它从PhotoDecodeRunnable接收状态代码,并将它传递到维护线程池和实例化的对象处理程序:

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

从PhotoTask对象,PhotoManager对象接收状态代码和PhotoTask对象的句柄。因为状态TASK_COMPLETE,创建一个消息包含状态和任务对象并将它发送到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()检查每个传入消息的状态码。如果TASK_COMPLETE状态代码,然后,任务完成后,PhotoTask对象在消息中包含一个位图和一个ImageView。因为Handler.handleMessage()在UI线程上运行,它可以安全地移动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);
                    }
                    ...
                }
                ...
            }
            ...
    }
...
}

Hander的更多相关文章

  1. android学习日记25--ANR和Hander消息机制

    1.ANR(Application Not Responding)定义 在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:A ...

  2. Handler 、 Looper 、Message异步消息处理线程机制( hander消息机制原理)

    Handler . Looper .Message 这三者都与Android异步消息处理线程相关的概念. 那么什么叫异步消息处理线程呢? 异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次, ...

  3. Android Handler机制 (一个Thead中可以建立多个Hander,通过msg.target保证MessageQueue中的每个msg交由发送message的handler进行处理 ,但是 每个线程中最多只有一个Looper,肯定也就一个MessageQuque)

    转载自http://blog.csdn.net/stonecao/article/details/6417364 在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长 ...

  4. android hander

    http://www.cnblogs.com/plokmju/p/android_Handler.html 前言 Android的消息传递机制是另外一种形式的“事件处理”,这种机制主要是为了解决And ...

  5. hander消息机制原理

    基本原理 线程中调用Handler.sendMsg()方法(参数是Message对象),将需要Main线程处理的事件 添加到Main线程的MessageQueue中,Main线程通过MainLoope ...

  6. 通过Hander进行界面刷新

    Timer timer; TimerTask task; Handler handler;//先声明这3个变量 //在onCreate方法内 handler = new Handler(){ @Ove ...

  7. android hander 线程用法

    @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanc ...

  8. Looper、Hander、HandlerThread

    一.Message .Looper.Handler之间的关系 1.系统发送的Message消息传送给Handler,Handler将Message放入自己的looper队列的底部   然后再从Loop ...

  9. hander消息机制原理(looper轮询监听机制)

    基本原理 线程中调用Handler.sendMsg()方法(参数是Message对象),将需要Main线程处理的事件 添加到Main线程的MessageQueue中,Main线程通过MainLoope ...

随机推荐

  1. WinDbg调试DMP格式文件

    前言:WinDbg是微软开发的免费源代码级的调试工具.WinDbg可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件.本文的讨论是在安装了Debugging Tools for Win ...

  2. hdu 3853 LOOPS 概率DP

    简单的概率DP入门题 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> #include ...

  3. IText 中文字体解决方案 生成doc文档

    IText生成doc文档需要三个包:iTextAsian.jar,iText-rtf-2.1.4.jar,iText-2.1.4.jar 亲测无误,代码如下: import com.lowagie.t ...

  4. HandlerThread 类的学习(转载)

    HandlerThread继承于Thread,所以它本质就是个Thread.HandlerThread类用于方便的创建一个含有looper的线程类,looper用来创建handler类.我们一般不创建 ...

  5. ANDROID_MARS学习笔记_S01_011ProgressBar

    文档是这样来设置样式 <ProgressBar android:layout_width="wrap_content" android:layout_height=" ...

  6. Android:@id和@+id

    @id代表引用已有的id,而@+id是新增加一个id 如果使用@+id/name形式,当R.java中存在名为name变量时,则该组件会使用该变量的值作为标识.如果不存在该变量,则添加一个新的变量,并 ...

  7. Android ActionBar隐藏修改图标和标题

    有时候在一些子页面或者内容页面,不需要显示ActionBar的标题栏图标.可用如下方式进行设置. 首先获取到ActionBar对象 ActionBar actionBar=getActionBar() ...

  8. 宏HASH_INSERT

    调用 方法 HASH_INSERT(lock_t, hash, lock_sys->rec_hash,lock_rec_fold(space, page_no), lock); /******* ...

  9. 设计模式 - observer

    简单来讲,就是observer依赖于subject,当subject发生变化时,observer得到通知,并将状态与subject同步,常来用于维护对象间状态的一致性. observer的工作过程大体 ...

  10. poj3186 poj3267

    两道很不错的dp 3186很神似回文词,合并石子之类的问题: 一开始不知道怎么在dp方程中体现权值天数,很来才想起来 对于一段区间[i,j],里面的东西必然是要卖完的 又因为只能从两头开始卖,所以 d ...