從源碼分析Service和IntentService的區別

Service:

概念:Service是一個在後臺執行長時間運行操作而不用提供用戶界面的應用組件,可由其他組件啓動,即使用戶切換到其他應用程序,Service 仍然在後臺繼續運行。
特徵:Service分爲兩種工作狀態,

  • 一種是啓動狀態,由startService方式啓動。一旦服務啓動,它就會在後臺無限期的運行,生命週期獨立於啓動它的組件,即使啓動它的組件已經銷燬了也不受任何影響。任務執行完成之後可以通過調用stopSelf()來停止服務,或者通過其他應用組件調用stopService
    來停止服務。這種 方式一般用於在後臺執行任務,而不需要返回結果給啓動組件。
  • 另一種是綁定方式,用bindservice連接。多個組件可以綁定到同一個服務上,如果只有一個組件綁定服務,當綁定的組件被銷燬時,服務也就會停止了。如果是多個組件綁定到一個服務上,當綁定到該服務的所有組件都被銷燬時,服務纔會停止。且Service還有一個特性,多次綁定同一個Service時,Service的onBind方法只會執行一次,除非Service被終止了。綁定服務的方式通常用於組件和服務之間相互通信。

且兩種方式可共存,即startService和bindService都可以執行多次,Service還是那一個實例。
線程
Service並不會新開啓線程執行,其onCreate等回調方法都是執行在主線程中的。不建議在Service中編寫耗時的操作邏輯,容易引起ANR。(10s超時)

IntenteService

概念:一種特殊的Service,繼承了Service並且是一個抽象類,可用於執行後臺耗時任務,任務執行完後,IntentService 會自動停止,不需要手動停止。
特徵:

  • IntentService會創建獨立的工作線程來處理任務請求。
  • 請求處理完成後,IntentService會自動停止,無需調用stopSelf()方法停止Service
  • 可以多次啓動 IntentService執行任務,而每一個耗時操作會以工作隊列的方式在IntentService 的onHandleIntent 回調方法中執行,且多個任務串行執行。
  • 比Service擁有更高優先級,適合高優先級的後臺任務,且不容易被系統殺死。

Intentservice源碼解讀

首先,IntentService是個抽象類,使用時必須實現此類。且其繼承自Service,即Service的子類,擁有父類Service的特性。

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;

然後,其內部的ServiceHandler即通過傳入線程的Looper創建Handler,且執行完onHandleIntent任務後調用stopSelf關閉自己。

  private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
        //這裏回調onHandleIntent到用戶子類實現具體任務處理工作。且執行在Looper所在的線程。
            onHandleIntent((Intent)msg.obj);
            //任務執行完後調用stopSelf關閉Service
            stopSelf(msg.arg1);
        }
    }

之後,是IntentService的onCreate方法,可以看到其創建了一個工作線程,新建了一個HandlerThread,並獲取HandlerThread的Looper初始化了ServiceHandler。即發送到Handler中處理的消息運行在這個HandlerThread線程中。 關於Handler的源碼理解,可以參考我的另一篇文章:Handler通信機制源碼解讀

 @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);
    }

接下來,Service的生命週期onStart,其中將傳進來的intent封裝進Message並通過handler發送到工作線程處理。而這個intent哪裏來的呢,現在我們回想下我們如何啓動Service。

這是我們常用的啓動service的代碼示例:

 Intent intent = new Intent(this,LocalIntentService.class);
    intent.putExtra("key","value");
    startService(intent);

在Service的源碼中,startService會調用onStartCommand回調,並把intent參數傳給後者,而如下IntentService源碼中顯示,其又回調了onStart方法,又將intent參數傳給了onStart,所以onStart方法中通過mServiceHandler發送的intent消息即是用戶startService帶的消息。

@Override
public void onStart(Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    //將傳進來的intent封裝進Message並通過handler發送到工作線程處理。
    mServiceHandler.sendMessage(msg);
}

public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
		//onStartCommand 直接調用的是onStart方法
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

最後,由於用戶繼承IntentService,實現onHandleIntent方法,而onHandleIntent又接受了intent參數,並在開始的HandlerThread中處理耗時任務。

這裏就分析完了Service和IntentService的區別,希望對大家有所幫助。歡迎討論,多多指教。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章