上一篇文章講了HandlerThread(http://www.reibang.com/p/5522de58c320)焰坪,這篇就講講使用到HandlerThread的IntentService桩砰。
先簡單介紹下IntentService,它繼承自Service本身也是抽象類残炮,因為Service本身是運行在主線程的,而在Service中開啟子線程需要主動去調(diào)用stopService()/stopSelf()才能停止運行军浆,容易遺忘或者邏輯漏洞導(dǎo)致Service無法及時關(guān)閉异赫,出現(xiàn)內(nèi)存泄露。IntentService就是用來解決這個問題的晴裹,本篇希望通過了分析其源碼了解其實現(xiàn)這一功能的邏輯被济。
使用:
必須實現(xiàn)一個構(gòu)造方法調(diào)用父類的含參構(gòu)造器和 void onHandleIntent(@Nullable Intent intent) 方法
public MyIntentService() {
super("thread_name");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
}
就是如此簡單,構(gòu)造方法的參數(shù)是開啟子線程的名字涧团,onHandleIntent會在子線程執(zhí)行(可以打印該線程的名字只磷,會發(fā)現(xiàn)和你傳入構(gòu)造器的參數(shù)是一樣的)并且在執(zhí)行完成后會關(guān)閉Service经磅。
實現(xiàn)邏輯
IntentService算上注釋一共也就181行,其實邏輯非常簡單钮追,簡述一下就是這樣的:
1.在onCreate中創(chuàng)建工作線程(創(chuàng)建的對象就是上文所提到的HandlerThread)预厌,然后獲取該線程綁定的Looper對象,并創(chuàng)建Handler綁定該Looper對象元媚。
2.在onStartCommand調(diào)用onStart轧叽,在onStart中創(chuàng)建Message對象并將intent意圖打包到Message中通過Handler發(fā)送Message來保證在指定線程執(zhí)行(也就是在onCreate創(chuàng)建的工作線程中執(zhí)行)
@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);
}
/**
* You should not override this method for your IntentService. Instead,
* override {@link #onHandleIntent}, which the system calls when the IntentService
* receives a start request.
* @see android.app.Service#onStartCommand
*/
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
這里有個重點就是Handler對象,如下刊棕,IntentService的內(nèi)部類ServiceHandler實現(xiàn)了自己的handleMessage方法炭晒,這也就是其整個邏輯的關(guān)鍵所在:
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);
}
}
最終執(zhí)行了onHandleIntent并將Intent傳入,沒毛病甥角。
然后网严,onHandleIntent執(zhí)行完成之后調(diào)用stopSelf結(jié)束service,到這里“IntentService如何實現(xiàn)執(zhí)行完任務(wù)后停止service的”這個問題就解決了嗤无。
其它細節(jié)
不過還有一點這里調(diào)用的stopSelf并不是我們?nèi)粘J褂玫膕topSelf()震束,它是帶參數(shù)的:stopSelf(msg.arg)中的參數(shù)其實是startId,我們再onStart()方法中構(gòu)建Message對象時會將它包裝在Message中当犯,他的作用其實就是保證我們所有的工作任務(wù)都完成了垢村,才會真正的關(guān)閉service。
也就是說我們可以重復(fù)的startService()執(zhí)行多項后臺任務(wù)嚎卫,service會重復(fù)執(zhí)行onStart()方法嘉栓,每次發(fā)送不同的Message對象,這樣子就可以像一個隊列一樣驰凛,確保每一項任務(wù)都完成之后再結(jié)束service胸懈,減少了多次創(chuàng)建service的消耗,可以說這個思路非常巧妙了恰响。