当前位置: 首页 > 编程笔记 >

Android后台线程和UI线程通讯实例

夔学智
2023-03-14
本文向大家介绍Android后台线程和UI线程通讯实例,包括了Android后台线程和UI线程通讯实例的使用技巧和注意事项,需要的朋友参考一下

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

 类似资料:
  • 线程间通讯接口 模块   信号量   信号量接口     互斥量   互斥量接口     事件   事件接口     邮箱   邮箱接口     消息队列   消息队列接口     信号   信号接口   结构体 struct   rt_ipc_object   IPC基类控制块 更多...   宏定义 #define  RT_IPC_FLAG_FIFO   0x00   先进先出模式   #de

  • 本文向大家介绍C#中前台线程和后台线程的区别与联系,包括了C#中前台线程和后台线程的区别与联系的使用技巧和注意事项,需要的朋友参考一下 前台线程和后台线程的区别和联系: 1、后台线程不会阻止进程的终止。属于某个进程的所有前台线程都终止后,该进程就会被终止。所有剩余的后台线程都会停止且不会完成。 2、可以在任何时候将前台线程修改为后台线程,方式是设置Thread.IsBackground 属性。 3

  • 问题内容: 我正在Xcode 9 beta,iOS 11中使用Google Maps。 我收到如下错误输出到日志: 主线程检查器:在后台线程上调用的UI API:-[UIApplication applicationState] PID:4442,TID:837820,线程名称:com.google.Maps.LabelingBehavior,队列名称:com.apple.root.default

  • 我正在编写一个Android应用程序,它连接到蓝牙设备,读取设备发送的数据,将其添加到AChartEngine图形中,并在文本视图中显示数据。 我的Bluetooth代码与BluetoothChat示例代码中的线程实现非常相似(它与SDK一起提供)。我可以在LogCat中看到< code>ConnectedThread循环正在执行并因此获得新数据,但我的TextView在7行之后停止更新,图形间歇

  • Java 8的promise实现,即CompletableFuture,提供了应用(…)和get()方法。 其中,在必要时等待promise完成,然后返回其结果。 现在假设我们使用(或)链接一些代码以在UI线程上运行(请参见stackoverflow.com/thenApply和thenApplyAsync之间的差异)。 如果我们在UI线程中调用,比如Java以某种方式处理这种情况,或者它会导致所