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方法中就可以接收到消息。
基本用法
- 创建HandlerThread实例
通过调用HandlerThread的构造函数并传入一个字符串作为线程名创建HandlerThread实例。
HandlerThread handlerThread = new HandlerThread("mHandlerThread");
"mHandlerThread"是线程的名字。
- 启动HandlerThread
在创建HandlerThread实例后,需要调用start()方法来启动线程。
handlerThread.start();
- 获取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());
}
};
- 发送消息到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方法");
}
});
- 处理消息
在Handler的handleMessage()方法中处理从主线程或其他线程发送过来的消息。
- 停止HandlerThread
通过调用Handler的quit()或quitSafely()方法来停止消息循环。HandlerThread在完成当前消息处理后终止。
handler.quit();
// 或者
handler.quitSafely();
- 注意事项
- 在HandlerThread停止后再处理与其相关的任何资源,避免潜在的内存泄漏或其他问题。
- HandlerThread中的任务是串行执行的,如果某个任务执行时间过长,可能会导致后续任务被延迟处理。
- 注意线程安全问题,确保在多个线程之间正确地同步和共享数据。