前面介紹的Service在官方文檔介紹中說Service存在着如下兩個問題:
1.A Service isnota separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
2.A Service isnota thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).
1、Service不會專門啟動一條單獨的程序,Service與它所在的應用在同一個程序中。
2、Service不是專門一條新的線程,是以不能再Service中直接處理耗時任務。
如果開發者在Service中處理耗時任務,建議在Service中另外啟動一條新的線程來處理耗時的任務,可能有的朋友就會問:“既然在Service中處理耗時任務需要啟動新線程,為什麼我們不直接在Activity中開啟一個新線程,而要使用Service呢?”
其實這種在Activity中直接啟動一個線程來實作對有些業務邏輯是非常不可靠的,比如:使用者使用BroadcastReceiver來啟動一個新線程,BroadcastReceiver的生命周期非常短,這樣就可能存在這樣的問題,在子線程還沒有結束的情況下,BroadcastReceiver已經結束了,或者使用者在Activity中啟動一個新線程後直接退出,此時它們所在的程序就變成了空程序(沒有任何活動元件的程序),系統需要記憶體時可能會優先終止該程序。如果宿主程序被終止,那麼該程序内的所有子線程也會被終止,這樣就有可能導緻一些嚴重錯誤。
IntentService是Service的子類,是以它比Service增加了額外的功能,它正好彌補了Service的上述兩點不足:IntentService将會使用隊列來管理請求Intent,每當用戶端代碼通過Intent請求啟動IntentService時,IntentService會将該Intent加入隊列中,然後開啟一條新的worker線程來處理該Intent.對于異步的startService()請求,IntentService會按次序依次處理隊列中的Intent,該線程保證同一時刻隻處理一個Intent.由于IntentService使用新的worker線程處理Intent請求,是以IntentService不會阻塞主線程,是以IntentService就可以處理耗時任務。
IntentService有如下特征:
1、會建立單獨的worker線程來處理所有的Intent請求。
2、會建立單獨的worker線程來處理onHandleIntent()方法實作的代碼。
3、所有請求處理完成後,IntentService會自動停止,是以開發者無須調用stopSelf()方法
4、為Service的onBind()方法提供了預設的實作,預設實作的onBind()方法傳回null
5、為Service的onStartCommand()方法提供了預設實作,該實作會将請求的Intent添加到隊列中。
從上面的特點中可以看出來,擴充的IntentService實作Service無須重寫onBind()方法和onStartCommand()方法,隻要重寫onHandleIntent()方法即可。
下面通過一個具體例子來說明IntentService和Service的差別:
(1)繼承自Service的MyService類
package com.example.testservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class MyService extends Service{
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//該方法内可以執行耗時任務,比如下載下傳檔案等
long endTime = System.currentTimeMillis() + 20 * 1000;
System.out.println("onStart");
while(System.currentTimeMillis() < endTime){
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("--耗時任務執行完畢--");
return START_STICKY;
}
}
讀者可能會注意到onStartCommand方法最後的傳回值我設定成了START_STICKY,有關傳回值的詳細設定及含義将在下一篇文章中介紹。
執行結果
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICdzFWRoRXdvN1LclHdpZXYyd2LcBzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX9QzVZlWNXllb1cVWzY0RaZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DOyMTOxkDNzETOxITMzEDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
可以看到在Service中執行耗時任務程式的主UI會被阻塞,出現ANR異常。
(2)繼承自IntentService的MyIntentService類
package com.example.testservice;
import android.app.IntentService;
import android.content.Intent;
public class MyIntentService extends IntentService{
public MyIntentService(){
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent arg0) {
//該方法内可以執行耗時任務,比如下載下傳檔案等
long endTime = System.currentTimeMillis() + 20 * 1000;
System.out.println("onStart");
while(System.currentTimeMillis() < endTime){
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("--耗時任務執行完畢--");
}
}
執行結果: