提示:閱讀本文之前可先閱讀Android個人筆記之Android的消息機制
HandlerThread本質(zhì)上就是一個普通Thread,只不過內(nèi)部建立了Looper.看下源碼
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
/**
* Returns the identifier of this thread. See Process.myTid().
*/
public int getThreadId() {
return mTid;
}
}
由此看出HandlerThread除了有個優(yōu)先級之外,與自己手動創(chuàng)建Looper的Thread并沒有什么不同锉走。這里有一個地方要理解一下锣险,也許你已經(jīng)發(fā)現(xiàn)了
run方法里面當(dāng)mLooper創(chuàng)建完成后有個notifyAll(),getLooper()中有個wait()勤篮,這是為什么呢?因為mLooper在HandlerThread中執(zhí)行,而我們的handler是在UI線程初始化的庐冯,也就是說,我們必須等到mLooper創(chuàng)建完成沿盅,才能正確的返回getLooper();wait(),notify()就是為了解決這兩個線程的同步問題把篓。
既然系統(tǒng)給我們提供了這么一個類,到底有什么好處呢腰涧?
HandlerThread的常規(guī)用法
- 啟動線程韧掩,構(gòu)造參數(shù):String代表線程名,priority代表優(yōu)先級窖铡。優(yōu)先級范圍為-20到19疗锐,默認(rèn)為0,優(yōu)先級越高费彼,獲得的CPU資源更多滑臊,反之則越少。-20代表優(yōu)先級最高箍铲,反之19最低雇卷。
mThread = new HandlerThread("handler_thread");
mThread.start();
- 創(chuàng)建處理任務(wù)的mWorkHandler和更新UI的mUIHandler。
mWorkHandler = new Handler(mThread.getLooper());
mUIHandler = new Handler();
- mWorkHandler與HandlerThread的Looper關(guān)聯(lián),并在handleMessage(Message msg)中處理任務(wù)颠猴,處理完之后通知mUIHandler對UI進行刷新关划。
- 在合適的時機退出HandlerThread,比如activity中的onDestroy(),方法有quit()和quitSafely()
具體處理方式要看具體需求,不過總體思路跟上面三個步驟差不多翘瓮。如果想處理多個任務(wù)贮折。就發(fā)送多個消息,在mWorkHandler進行處理资盅。
HandlerThread的特點
- HandlerThread將loop轉(zhuǎn)到子線程中處理调榄,說白了就是將分擔(dān)MainLooper的工作量,降低了主線程的壓力呵扛,使主界面更流暢每庆。
- 開啟一個線程起到多個線程的作用。處理任務(wù)是串行執(zhí)行今穿,按消息發(fā)送順序進行處理扣孟。
相比多次使用new Thread(){…}.start()這樣的方式節(jié)省系統(tǒng)資源。
但是由于每一個任務(wù)都將以隊列的方式逐個被執(zhí)行到荣赶,一旦隊列中有某個任務(wù)執(zhí)行時間過長凤价,那么就會導(dǎo)致后續(xù)的任務(wù)都會被延遲處理。 - HandlerThread擁有自己的消息隊列拔创,它不會干擾或阻塞UI線程利诺。
- 通過設(shè)置優(yōu)先級就可以同步工作順序的執(zhí)行,而又不影響UI的初始化剩燥;
總結(jié)
HandlerThread比較適用于單線程+異步隊列的場景慢逾,比如IO讀寫操作立倍,耗時不多而且也不會產(chǎn)生較大的阻塞。對于網(wǎng)絡(luò)IO操作侣滩,HandlerThread并不適合口注,因為它只有一個線程,還得排隊一個一個等著君珠。