Hander

多线程与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,布布扣,bubuko.com

时间: 2024-10-13 03:13:29

Hander的相关文章

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

转载自http://blog.csdn.net/stonecao/article/details/6417364 在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长时间的任务后做出相应的通知 handler基本使用: 在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法,在handleMessage中 提供收到消息后相应的处理方法即可,这里不对handler使用进行详细说明,在看本博文前,读者应该先掌握hand

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

Handler . Looper .Message 这三者都与Android异步消息处理线程相关的概念. 那么什么叫异步消息处理线程呢? 异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环.若消息队列为空,线程则会阻塞等待. 详细总结::: 前提,主线程ui,只能刷新页面和处理事件:耗时的数据处理都在子线程中... 那么子线程的数据如何同步到主线程? 那就需要异步消息处理机制Handler .

android hander 线程用法

@Override public void onClick(View v) { lsh = "576"; startdate = setstart_date.getText().toString(); enddate = setend_date.getText().toString(); btnLoginContext = v.getContext(); HandlerThread handlerThread = new HandlerThread("handlerThrea

android hander

http://www.cnblogs.com/plokmju/p/android_Handler.html 前言 Android的消息传递机制是另外一种形式的“事件处理”,这种机制主要是为了解决Android应用中多线程的问题,在Android中不允许Activity新启动的线程访问该Activity里的UI组件,这样会导致新启动的线程无法改变UI组件的属性值.但实际开发中,很多地方需要在工作线程中改变UI组件的属性值,比如下载网络图片.动画等等.本篇博客主要介绍Handler是如何发送与处理线

Hander实现引导页

使用Hander实现引导页: 代码: /** * 引导页 */ public class SplashActivity extends Activity { private static final int GO_MAIN = 1000; //延迟时间 private static final long SPLASH_DELAY_MILLIS = 500; @Override protected void onCreate ( @Nullable Bundle savedInstanceStat

Android Hander、Looper、Message三者之间的联系

1.首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象:因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个.2.Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法.3.Handler的构造方法,会首先得到当前线程中保存的Looper实例,

hander消息机制原理

基本原理 线程中调用Handler.sendMsg()方法(参数是Message对象),将需要Main线程处理的事件 添加到Main线程的MessageQueue中,Main线程通过MainLooper从消息队列中取出Handler发过来的这个消息时,会回调 Handler的handlerMessage()方法. 注意:(UI主要线程中才有Looper)创建一个Handler时一定要关联一个Looper实例,默认构造方法Handler(),它是关联当前Thread的Looper在创建一个Hand

android hander如何避免内存泄露

在使用Android Handler的时候,可能会遇到编译器给我们这样的警告: This Handler class should be static or leaks might occur 造成这个警告的原因是handler持有外层类(Activity等)的引用,同时消息队列中的Message对handler也持有引用,这样就造成一些资源不能回,从而可能造成内存泄露. 解决这个警告的办法即让handler不持有外部类的引用,怎么做到这一点呢,即将Handler设置为静态内部类就行了,将外部类

hander同步技巧 利用post之后的消息是最后完成的,实现同步。关键看waitDone的实现。带面精简Camera应用。

private void testWait(){ HandlerThread ht = new HandlerThread("Camera Handler Thread"); ht.start(); mCameraHandler = new CameraHandler(ht.getLooper()); mCameraHandler.obtainMessage(OPEN_CAMERA, 1, 0).sendToTarget(); boolean ret = false; ret = mC