HandlerThread 是線程類斤葱,主動綁定 Looper 哑蔫,為 Handler 提供了消息隊(duì)列闭树,IntentService 中通過為 Handler 綁定 HandlerThread 提供的子線程 Looper漾峡,從而使 Handler 處理消息在子線程幔烛,由于 Looper 是死循環(huán)导而,所以在 IntentService 銷毀時(shí)辕录,必須停止 Looper 中消息隊(duì)列的循環(huán) MessageQueue.quit() 玫鸟,從而停止 HandlerThread退渗。
HandlerThread 原理解析
繼承了 Thread 類移稳,是一個(gè)線程類,在 run() 方法中 調(diào)用了 Looper.prepare() 和 Looper.loop() 方法会油,所以該線程默認(rèn)已經(jīng)綁定了 Looper
還提供了獲取綁定的 Looper 對象的方法 getLooper(); 調(diào)用該方法時(shí)如果 Looper 沒有初始化則調(diào)用該方法的該線程會 wait() 等待个粱,Looper 對象綁定之后則會 notifyAll(); 喚醒所有 wait() 的線程,從而保證了 getLooper() 方法會得到正確的 Looper 對象钞啸。
獲取到 Looper 之后就可以創(chuàng)建與該子線程綁定的 Handler 几蜻,通過 Handler 就可以發(fā)送消息,從而在子線程中處理消息体斩。
HandlerThread 的 run 方法為一個(gè)死循環(huán)梭稚,終止運(yùn)行 使用 quit 方法和 quitSafely 方法,兩個(gè)方法的區(qū)別是 MessageQueue 消息隊(duì)列中對消息的處理
quit 方法中直接回收每一個(gè)消息絮吵,quitSafely 中會將大于當(dāng)前時(shí)間的未處理消息直接回收弧烤,對已經(jīng)開始執(zhí)行的消息,會安全回收
HandlerThread 存在意義
HandlerThread 作為一個(gè)線程對象蹬敲,其存在意義為暇昂,提供了一個(gè)綁定到子線程的 Looper ,從而得到在子線程中輪詢的消息隊(duì)列伴嗡, 從而可以初始化時(shí) Handler 綁定的消息隊(duì)列為子線程急波。
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll(); // 喚醒 wait() 的線程
}
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(); // 等待 Looper 對象創(chuàng)建
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
IntentService
- 繼承了 Service 類,是服務(wù)瘪校。使用時(shí)需要重寫其內(nèi)部的抽象方法 onHandleIntent() ;
- 在 onCreat() 方法中創(chuàng)建了 HandlerThread 對象澄暮,通過調(diào)用 HandlerThread 對象的 getLooper() 方法得到了子線程的 Looper 對象;
- 接著通過該 Looper 對象創(chuàng)建了內(nèi)部類 ServiceHandler 的對象阱扬,該 ServiceHandler 處理消息時(shí)在 HandlerThread 線程中泣懊。
- 接著在 onStart() 方法中,調(diào)用 ServiceHandler 的 obtainMessage() 方法創(chuàng)建了一個(gè) Message 對象麻惶,該方法是 Handler 中的方法馍刮,實(shí)現(xiàn)是通過調(diào)用 Message.obtain(); 方法創(chuàng)建 Message 對象,obtain() 方法需要一個(gè) Handler 對象窃蹋,傳入 ServiceHandler 本身即可卡啰。創(chuàng)建 Message 對象后静稻,使用 ServiceHandler 將消息發(fā)送出去。
- ServiceHandler 發(fā)送消息后碎乃,根據(jù)消息處理機(jī)制 ServiceHandler 會收到該消息姊扔,此時(shí)即調(diào)用重寫的 IntentSErvice 的 onHandleIntent() 方法惠奸,在 子線程(ServiceHandler 中的 HandlerThread) 中處理消息梅誓。
- 最終實(shí)現(xiàn)了 Service 運(yùn)行在子線程。
- 處理完消息后調(diào)用了 stopSelf(int id) 方法佛南,之所以沒有調(diào)用 stopSelf() 方法是因?yàn)楣j绻麤]有參數(shù),會直接停止該 Service嗅回,由于 Service 可能被啟動多次及穗,所以調(diào)用 stopSelf 帶參數(shù)的方法,只有當(dāng)參數(shù) id 同啟動 Service 的次數(shù)相同是 Service 才會停止绵载,因?yàn)橄㈥?duì)列中的消息是依次處理的埂陆,所以最后一個(gè)處理結(jié)束后,調(diào)用 StopSelf 帶參數(shù)的方法會正常停止 Service
- 在 IntentService 的 onDestory 方法中執(zhí)行了 mServiceLooper 的 quit 方法娃豹,停止 HandlerTreand 中 Looper 的死循環(huán)焚虱,從而安全的退出 HandlerThread 線程。
ServiceHandler (繼承了 Handler 類懂版,是一個(gè) Handler類鹃栽,其 handleMessage() 方法調(diào)用了 IntentService類 的一個(gè)抽象方法 onHandleIntent() 來處理消息。處理完成之后就會自動結(jié)束)
public abstract class IntentService extends Service {
/**
* 內(nèi)部類 ServiceHandler
*/
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
protected abstract void onHandleIntent(@Nullable Intent intent);
@Override
public void onDestroy() {
mServiceLooper.quit();
}
}
IntentService 是一個(gè)抽象的服務(wù)類躯畴,使用時(shí)只需要新子類繼承 IntentService 并重寫其抽象方法 onHandleIntent() 調(diào)用類其對象的 start() 方法之后民鼓,則在子線程中執(zhí)行 onHandleIntent() 中的代碼。