Android開發(fā)中胚鸯,經(jīng)常會遇到耗時操作谬墙,比如下載文件吵聪,這個時候大家第一個想法就是交給Service去處理劲装,而Service并不能夠直接去處理耗時請求胧沫,所以我們都會在Service中開啟子線程去做這些事情昌简。那么在這個過程我們需要處理好2個問題。
1.在需要添加任務(wù)的時候就在Service中開啟線程并且執(zhí)行任務(wù)绒怨。
2.在任務(wù)結(jié)束之后關(guān)閉Service纯赎。
而IntentService將這2個問題處理得很好了。
在IntentService中南蹂,有一個私有內(nèi)部Handler的實現(xiàn)犬金。
private volatile ServiceHandler mServiceHandler;
...
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);
}
}
mServiceHandler用來向內(nèi)部的HandlerThread發(fā)送需要執(zhí)行的任務(wù)。
首先六剥,在Service創(chuàng)建的時候晚顷,會啟動一個HandlerThread線程來執(zhí)行任務(wù),并且使用HandlerThread的Looper實例化mServiceHandler疗疟。
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);
}
然后就可以通過mServiceHandler來向HandlerThread推送需要執(zhí)行的任務(wù)该默。
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
而onHandleIntent(@Nullable Intent intent)方法就是我們執(zhí)行具體耗時操作的地方了,通過將intent消息體傳遞進(jìn)來策彤,解析消息之后再進(jìn)行具體的耗時操作栓袖。
在ServiceHandler中的handleMessage方法中,使用stopSelf(msg.arg1)來停止線程店诗。也就是在我們耗時任務(wù)執(zhí)行完成之后裹刮,再去停止線程。
這樣很好的解決了上面的2個問題了庞瘸,而且在停止線程的時候使用stopSelf(msg.arg1)捧弃,這樣能夠規(guī)避一個新的問題。
當(dāng)Service要同時處理多個請求擦囊,你就不能在當(dāng)前一個請求處理完成之后立刻停止Service违霞,因為很可能現(xiàn)在你已經(jīng)收到了一個新的啟動Service請求(如果立刻停止,那么新來的請求就會跟著終止)霜第。
stopSelf(int)可以保證Service當(dāng)前停止的請求是基于上一個請求的葛家,因為當(dāng)我們每次startService之后户辞,Service都會有一個新的startID泌类,而通過上面的代碼我們可以找到msg.arg1就是這個startID。
public void onStart(@Nullable Intent intent, int startId) {
...
msg.arg1 = startId;
...
}
那么當(dāng)stopSelf要停止的Service的startID和當(dāng)前IntentService的startID是不相同的底燎,這個時候是無法殺死Service的刃榨,這樣就能保證Service在處理多個請求的時候存活了。
另外双仍,IntentService是屬于non-sticky服務(wù)的枢希,也就是說它會在任務(wù)完成之后自己停止,所以它并不適合那種需要一直生存在后臺的Servie朱沃。
IntentService管理自啟是當(dāng)Service設(shè)置為重要時苞轿,那么他會一直運行到?jīng)]有任務(wù)了才會自己關(guān)閉茅诱,也就是說當(dāng)系統(tǒng)殺掉IntentService之后,它會自動啟動搬卒,并且把對應(yīng)的Intent傳遞進(jìn)來瑟俭,而當(dāng)沒有設(shè)置重要度的時候,也就是默認(rèn)不重要的時候契邀,當(dāng)被系統(tǒng)殺掉之后摆寄,就不會再自動啟動了。
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
-START_REDELIVER_INTENT:在運行onStartCommand后service進(jìn)程被kill后坯门,并且沒有新的intent傳遞給它微饥。Service將移出開始狀態(tài),并且直到新的明顯的方法(startService)調(diào)用才重新創(chuàng)建古戴。因為如果沒有傳遞任何未決定的intent那么service是不會啟動欠橘,也就是期間onstartCommand不會接收到任何null的intent。
-START_NOT_STICKY:在運行onStartCommand后service進(jìn)程被kill后现恼,系統(tǒng)將會再次啟動service简软,并傳入最后一個intent給onstartCommand。直到調(diào)用stopSelf(int)才停止傳遞intent述暂。如果在被kill后還有未處理好的intent痹升,那被kill后服務(wù)還是會自動啟動。因此onstartCommand不會接收到任何null的intent畦韭。
mRedelivery可以通過set方法進(jìn)行設(shè)置疼蛾。
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}