IntentService與普通的Service最大的區(qū)別在于,通過(guò)startService啟動(dòng)的普通Service,如果不主導(dǎo)調(diào)stopService方法,那么這個(gè)service會(huì)在后臺(tái)一直存在。 而通過(guò)startService啟動(dòng)的IntentService,他在執(zhí)行完所有異步任務(wù)后,會(huì)自己銷(xiāo)毀。
通過(guò)查看源碼,我們知道 IntentService 實(shí)際上是繼承了Service類(lèi)的,他與普通Service不同的是,它定義了一個(gè)ServiceLooper和ServiceHandler。

當(dāng)我們啟動(dòng)一個(gè)IntentService的時(shí)候,首先會(huì)進(jìn)入Service的onCreate方法,我們來(lái)看看IntentService在onCreate方法里都做了些什么。
@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);
}
從代碼中可以看到,它創(chuàng)建一個(gè)HandlerThread的線(xiàn)程,然后直接啟動(dòng)這個(gè)線(xiàn)程,
然后再初始化上面說(shuō)的mServiceLooper和mServiceHandler.(如果不知道handler,looper工作原理的自行查閱)。
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);//handler使用的looper是HandlerThread里的,
//也就是說(shuō)使用該handler發(fā)送的消息都會(huì)到 HandlerThread 的 Looper的 MessageQueue中。
在HandlerThread的run方法中,Looper.loop() 進(jìn)入循環(huán)等待mServiceHandler發(fā)送的消息

。
當(dāng)有消息會(huì)回調(diào)到mServiceHandler的handleMessage方法中,在這里
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
有一個(gè)抽象方法 onHandleIntent 去處理異步任務(wù),同時(shí)會(huì)調(diào)用stopSelf(msg.arg1);去停止服務(wù),但是這個(gè)服務(wù)不是直接停止,需要等所有的異步任務(wù) 處理完成之后才會(huì)去銷(xiāo)毀自己。 待會(huì)我們用代碼去驗(yàn)證這一點(diǎn)。
當(dāng)IntentService中所有的異步任務(wù)都執(zhí)行完成后,會(huì)銷(xiāo)毀掉。 那我們啟動(dòng)的HandlerThread什么時(shí)候銷(xiāo)毀呢,如果不銷(xiāo)毀每啟動(dòng)一次IntentService創(chuàng)建個(gè)異步線(xiàn)程,那顯然是不合理的。 關(guān)鍵就在于IntentSerice的 onDestory方法。
@Override
public void onDestroy() {
mServiceLooper.quit();
}
對(duì)應(yīng)到looper中的quit方法
/**
* Quits the looper.
* <p>
* Causes the {@link #loop} method to terminate without processing any
* more messages in the message queue.
* </p><p>
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
* For example, the {@link Handler#sendMessage(Message)} method will return false.
* </p><p class="note">
* Using this method may be unsafe because some messages may not be delivered
* before the looper terminates. Consider using {@link #quitSafely} instead to ensure
* that all pending work is completed in an orderly manner.
* </p>
*
* @see #quitSafely
*/
public void quit() {
mQueue.quit(false);
}
這樣,looper就退出循環(huán)了。HandlerThread run方法執(zhí)行完也就銷(xiāo)毀了。
下面通過(guò)例子來(lái)看,定義一個(gè)IntentService:
public class MyIntentService extends IntentService {
public MyIntentService(){
super("MyIntentService");
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public MyIntentService(String name) {
super(name);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
super.onStart(intent, startId);
Log.i("dx startId",String.valueOf(startId));
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i("dx", String.valueOf(Thread.currentThread().getId()));
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i("dx onDestroy","onDestroy");
}
}
我們?cè)趏nHandleIntent 讓工作線(xiàn)程停止兩秒來(lái)模擬耗時(shí)任務(wù),然后打印出當(dāng)前工作線(xiàn)程的pid。
在activity中定義一個(gè)圖片的點(diǎn)擊事件,每點(diǎn)擊一次,啟動(dòng)一次IntentService
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,MyIntentService.class);
startService(intent);
}
});
我們點(diǎn)擊一次。

可以看到,Service的銷(xiāo)毀是在異步任務(wù)結(jié)束之后才銷(xiāo)毀的。
我們?cè)倏焖龠B續(xù)點(diǎn)擊三次,啟動(dòng)三次Service:

通過(guò)log我們可以看到,當(dāng)service啟動(dòng)后,如果它還在執(zhí)行異步任務(wù),沒(méi)有銷(xiāo)毀,你再次啟動(dòng)它,他是不會(huì)走onCreate方法的。 因?yàn)檫@三次打印出來(lái)的pid都是同一個(gè),說(shuō)明HandlerThread 還是第一次new出來(lái)的那個(gè)。 當(dāng)過(guò)了6秒,三個(gè)異步任務(wù)都執(zhí)行完之后,我們的IntentService才銷(xiāo)毀。