原理解析 | Android中HandlerThread原理和使用
HandlerThread是Android開發(fā)中用于啟動具有Looper的新線程的線程類,內(nèi)部包含一個Looper和一個Handler,可以方便地發(fā)送和處理消息。通過在HandlerThread中處理任務,并通過Handler將結(jié)果發(fā)送回主線程,可以實現(xiàn)線程間的數(shù)據(jù)傳遞和交互。
原理解析
通過調(diào)用HandlerThread的構(gòu)造函數(shù)并傳入一個字符串作為線程名創(chuàng)建HandlerThread實例。
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}HandlerThread繼承于Thread,本質(zhì)上是一個線程,其構(gòu)造方法主要是做一些初始化的操作。
我們知道了HandlerThread類其實就是一個Thread,start()方法內(nèi)部調(diào)用的肯定是Thread的run方法,我們查看一下其run方法的具體實現(xiàn)。
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}內(nèi)部調(diào)用了Looper.prepate()方法和Loop.loop()方法,熟悉Android異步消息機制知道,在Android體系中是對應著Looper對象、MessageQueue對象,以及Handler對象。
所以通過run方法,我們可以知道在我們創(chuàng)建的HandlerThread線程中我們創(chuàng)建了該線程的Looper與MessageQueue。
這里需要注意的是其在調(diào)用Looper.loop()方法之前調(diào)用了一個空的實現(xiàn)方法onLooperPrepared(),我們可以實現(xiàn)自己的onLooperPrepared方法做一些Looper的初始化操作;
run方法里面當mLooper創(chuàng)建完成后有個notifyAll(),getLooper()中有個wait()。因為mLooper在一個線程中執(zhí)行,而我們的Handler是在UI線程初始化的,也就是說,我們必須等到mLooper創(chuàng)建完成,才能正確的返回getLooper()。wait()``notify()就是為了解決這兩個線程的同步問題。
我們使用時需要初始化Handler實例:
Handler handler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
// 處理消息
Log.i("HandlerThread", "接收到消息:" + msg.obj.toString());
}
};Handler的構(gòu)造方法中傳入了HandlerThread的Looper對象,所以Handler對象就擁有了HandlerThread線程中Looper對象的引用。調(diào)用Handler的sendMessage方法發(fā)送消息,在Handler的handleMessge方法中就可以接收到消息。
基本用法
- 創(chuàng)建HandlerThread實例
通過調(diào)用HandlerThread的構(gòu)造函數(shù)并傳入一個字符串作為線程名創(chuàng)建HandlerThread實例。
HandlerThread handlerThread = new HandlerThread("mHandlerThread");"mHandlerThread"是線程的名字。
- 啟動HandlerThread
在創(chuàng)建HandlerThread實例后,需要調(diào)用start()方法來啟動線程。
handlerThread.start();- 獲取Handler
HandlerThread啟動后,通過調(diào)用getLooper()方法并將其傳遞給Handler的構(gòu)造函數(shù)來獲取一個與HandlerThread關(guān)聯(lián)的Handler實例,用于在HandlerThread中發(fā)送和處理消息。
Handler handler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
// 處理消息
Log.i("HandlerThread", "接收到消息:" + msg.obj.toString());
}
};- 發(fā)送消息到HandlerThread
使用上一步中創(chuàng)建的Handler實例發(fā)送消息到HandlerThread。
// 使用sendMessage()方法發(fā)送消息
Message message = Message.obtain();
message.obj = "111111";
handler.sendMessage(message);
message = Message.obtain();
message.obj = "222222";
handler.sendMessage(message);
// 或者使用post()方法發(fā)送Runnable對象
handler.post(new Runnable() {
@Override
public void run() {
Log.i("HandlerThread", "執(zhí)行Runnable的run方法");
}
});- 處理消息
在Handler的handleMessage()方法中處理從主線程或其他線程發(fā)送過來的消息。
- 停止HandlerThread
通過調(diào)用Handler的quit()或quitSafely()方法來停止消息循環(huán)。HandlerThread在完成當前消息處理后終止。
handler.quit();
// 或者
handler.quitSafely();- 注意事項
- 在HandlerThread停止后再處理與其相關(guān)的任何資源,避免潛在的內(nèi)存泄漏或其他問題。
- HandlerThread中的任務是串行執(zhí)行的,如果某個任務執(zhí)行時間過長,可能會導致后續(xù)任務被延遲處理。
- 注意線程安全問題,確保在多個線程之間正確地同步和共享數(shù)據(jù)。
























