原理解析 | Android中HandlerThread原理和使用

移动开发 Android
我们知道了HandlerThread​类其实就是一个Thread,start()​方法内部调用的肯定是Thread的run​方法,我们查看一下其run方法的具体实现。

HandlerThread是Android开发中用于启动具有Looper的新线程的线程类,内部包含一个Looper和一个Handler,可以方便地发送和处理消息。通过在HandlerThread中处理任务,并通过Handler将结果发送回主线程,可以实现线程间的数据传递和交互。

原理解析

通过调用HandlerThread的构造函数并传入一个字符串作为线程名创建HandlerThread实例。

public HandlerThread(String name) {
    super(name);
    mPriority = Process.THREAD_PRIORITY_DEFAULT;
}

HandlerThread继承于Thread,本质上是一个线程,其构造方法主要是做一些初始化的操作。

我们知道了HandlerThread类其实就是一个Thread,start()方法内部调用的肯定是Thread的run方法,我们查看一下其run方法的具体实现。

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

内部调用了Looper.prepate()方法和Loop.loop()方法,熟悉Android异步消息机制知道,在Android体系中是对应着Looper对象、MessageQueue对象,以及Handler对象。

所以通过run方法,我们可以知道在我们创建的HandlerThread线程中我们创建了该线程的Looper与MessageQueue。

这里需要注意的是其在调用Looper.loop()方法之前调用了一个空的实现方法onLooperPrepared(),我们可以实现自己的onLooperPrepared方法做一些Looper的初始化操作;

run方法里面当mLooper创建完成后有个notifyAll(),getLooper()中有个wait()。因为mLooper在一个线程中执行,而我们的Handler是在UI线程初始化的,也就是说,我们必须等到mLooper创建完成,才能正确的返回getLooper()。wait()``notify()就是为了解决这两个线程的同步问题。

我们使用时需要初始化Handler实例:

Handler handler = new Handler(handlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        // 处理消息
        Log.i("HandlerThread", "接收到消息:" + msg.obj.toString());
    }
};

Handler的构造方法中传入了HandlerThread的Looper对象,所以Handler对象就拥有了HandlerThread线程中Looper对象的引用。调用Handler的sendMessage方法发送消息,在Handler的handleMessge方法中就可以接收到消息。

基本用法

  1. 创建HandlerThread实例

通过调用HandlerThread的构造函数并传入一个字符串作为线程名创建HandlerThread实例。

HandlerThread handlerThread = new HandlerThread("mHandlerThread");

"mHandlerThread"是线程的名字。

  1. 启动HandlerThread

在创建HandlerThread实例后,需要调用start()方法来启动线程。

handlerThread.start();
  1. 获取Handler

HandlerThread启动后,通过调用getLooper()方法并将其传递给Handler的构造函数来获取一个与HandlerThread关联的Handler实例,用于在HandlerThread中发送和处理消息。

Handler handler = new Handler(handlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        // 处理消息
        Log.i("HandlerThread", "接收到消息:" + msg.obj.toString());
    }
};
  1. 发送消息到HandlerThread

使用上一步中创建的Handler实例发送消息到HandlerThread。

// 使用sendMessage()方法发送消息
Message message = Message.obtain();
message.obj = "111111";
handler.sendMessage(message);

message = Message.obtain();
message.obj = "222222";
handler.sendMessage(message);

// 或者使用post()方法发送Runnable对象
handler.post(new Runnable() {
    @Override
    public void run() {
        Log.i("HandlerThread", "执行Runnable的run方法");
    }
});
  1. 处理消息

在Handler的handleMessage()方法中处理从主线程或其他线程发送过来的消息。

  1. 停止HandlerThread

通过调用Handler的quit()或quitSafely()方法来停止消息循环。HandlerThread在完成当前消息处理后终止。

handler.quit(); 
// 或者 
handler.quitSafely();
  1. 注意事项
  • 在HandlerThread停止后再处理与其相关的任何资源,避免潜在的内存泄漏或其他问题。
  • HandlerThread中的任务是串行执行的,如果某个任务执行时间过长,可能会导致后续任务被延迟处理。
  • 注意线程安全问题,确保在多个线程之间正确地同步和共享数据。
责任编辑:武晓燕 来源: 沐雨花飞蝶
相关推荐

2023-02-28 09:07:18

ChatGPTAI

2019-12-06 10:59:20

JavaScript运行引擎

2021-01-12 14:46:34

Kubernetes开发存储

2021-07-12 09:45:36

NameServer 核心Conusmer

2021-07-05 07:51:43

JVM底层Python

2021-05-14 06:15:48

SpringAware接口

2020-05-21 13:25:43

Spring组件架构

2021-12-01 18:36:35

属性

2023-08-11 07:44:40

TCP滑动窗口数据

2021-04-13 07:58:36

测试假设检验

2010-09-08 11:39:01

蓝牙协议栈语音网关

2015-08-18 09:40:32

OpenStack Neutron虚拟网络

2015-08-19 10:36:24

Zigbee技术无线通信

2023-11-16 09:01:37

Hadoop数据库

2010-07-06 10:07:10

jQueryJSON

2015-07-01 13:34:22

Kubernetes应用部署模型

2021-06-16 15:18:03

鸿蒙HarmonyOS应用

2017-11-28 15:36:25

换扶技术Android资源

2009-11-04 13:08:29

ADO.NET Dat

2021-05-19 15:40:54

HTTPS前端加密
点赞
收藏

51CTO技术栈公众号