主目錄見:Android高級進階知識(這是總目錄索引)
[written by Ticoo]
HandlerThread
顧名思義,HandlerThread它是一個Thread,是Google為提高開發(fā)者效率封裝的一個類。
與普通的Thread不同的是,它有一個成員屬性 Looper,而Looper是用來干嘛的前一章節(jié)我們已經(jīng)介紹過了。也就是說,我們的HandlerThread具有了Looper的功能。如果你有看過HandlerThread的源碼,你會發(fā)現(xiàn)它非常短,一百多行代碼。那,我們先來看線程最核心的run方法
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
沒錯,這就是我們在子線程里使用Handler時的典型用法
Looper.prepare(), Looper.loop()的使用,不同的是這里使用了一個鎖,
synchronized我們當(dāng)前的這個類實例,并且調(diào)用notifyAll()。為什么要多寫這個呢?看到這里我也不曉得。
當(dāng)我們對消息隊列的處理影響到性能的時候,比如頁面上的卡頓或者比較耗時的任務(wù),那我們就可以考慮使用HandlerThread了,來看看他的用法:
private Handler mHandler;
private HandlerThread mHandlerThread;
public void initHandler() {
mHandlerThread = new HandlerThread(Tag);
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
}
我們知道,在主線程里使用Hander,我們不需要再調(diào)用Looper.prepare()和Looper.loop(),因為系統(tǒng)已經(jīng)幫我們處理好了,主線程里的Handler使用的主線程的Looper。
使用HandlerThread,我們就可以在初始化Handler的時候,將HandlerThread里的Looper傳遞給Handler。這樣,主線程里Handler消息處理就會被轉(zhuǎn)移到子線程里,這樣一定程度上減少了主線程的壓力。
回頭來看源碼:
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;
}
初始化時getLooper(),我們發(fā)現(xiàn),這里也有一個鎖,也是鎖住HandlerThread類實例。start HandlerThread時,會調(diào)用其run方法,run方法里會調(diào)用 Looper.prepare() 需要一定的時間, 所以在new Handler時,wait()方法等待Looper初始化完成,所以在run方法里才會有
notifyAll()的調(diào)用。
以上就是對HandlerThread的分析,是不是挺簡單的呢?
根據(jù)以上的分析我們可以總結(jié)出:
- HandlerThread將Looper轉(zhuǎn)移到子線程中處理,降低主線程的壓力,不會阻塞主線程,界面顯示會更流暢
- 子線程處理消息,因此可以處理一些比較耗時的單個任務(wù)。
- 由于使用消息隊列的處理方式,故并發(fā)的多任務(wù)并不適用HandlerThread,會造成嚴重的阻塞