提示:閱讀本文之前可先閱讀Android個人筆記之Android的消息機制
HandlerThread本質上就是一個普通Thread,只不過內部建立了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并沒有什么不同。這里有一個地方要理解一下,也許你已經發(fā)現了
run方法里面當mLooper創(chuàng)建完成后有個notifyAll(),getLooper()中有個wait(),這是為什么呢?因為mLooper在HandlerThread中執(zhí)行,而我們的handler是在UI線程初始化的,也就是說,我們必須等到mLooper創(chuàng)建完成,才能正確的返回getLooper();wait(),notify()就是為了解決這兩個線程的同步問題。
既然系統(tǒng)給我們提供了這么一個類,到底有什么好處呢?
HandlerThread的常規(guī)用法
- 啟動線程,構造參數:String代表線程名,priority代表優(yōu)先級。優(yōu)先級范圍為-20到19,默認為0,優(yōu)先級越高,獲得的CPU資源更多,反之則越少。-20代表優(yōu)先級最高,反之19最低。
mThread = new HandlerThread("handler_thread");
mThread.start();
- 創(chuàng)建處理任務的mWorkHandler和更新UI的mUIHandler。
mWorkHandler = new Handler(mThread.getLooper());
mUIHandler = new Handler();
- mWorkHandler與HandlerThread的Looper關聯,并在handleMessage(Message msg)中處理任務,處理完之后通知mUIHandler對UI進行刷新。
- 在合適的時機退出HandlerThread,比如activity中的onDestroy(),方法有quit()和quitSafely()
具體處理方式要看具體需求,不過總體思路跟上面三個步驟差不多。如果想處理多個任務。就發(fā)送多個消息,在mWorkHandler進行處理。
HandlerThread的特點
- HandlerThread將loop轉到子線程中處理,說白了就是將分擔MainLooper的工作量,降低了主線程的壓力,使主界面更流暢。
- 開啟一個線程起到多個線程的作用。處理任務是串行執(zhí)行,按消息發(fā)送順序進行處理。
相比多次使用new Thread(){…}.start()這樣的方式節(jié)省系統(tǒng)資源。
但是由于每一個任務都將以隊列的方式逐個被執(zhí)行到,一旦隊列中有某個任務執(zhí)行時間過長,那么就會導致后續(xù)的任務都會被延遲處理。 - HandlerThread擁有自己的消息隊列,它不會干擾或阻塞UI線程。
- 通過設置優(yōu)先級就可以同步工作順序的執(zhí)行,而又不影響UI的初始化;
總結
HandlerThread比較適用于單線程+異步隊列的場景,比如IO讀寫操作,耗時不多而且也不會產生較大的阻塞。對于網絡IO操作,HandlerThread并不適合,因為它只有一個線程,還得排隊一個一個等著。