天天看點

Service.onStartCommand()詳解

啟動service的時候,onCreate方法隻有第一次會調用,onStartCommand和onStart每次都被調用。onStartCommand會告訴系統如何重新開機服務,如判斷是否異常終止後重新啟動,在何種情況下異常終止

onStartCommand和onStart差別

/**
     * @deprecated Implement {@link #onStartCommand(Intent, int, int)} instead.
     */
    @Deprecated
    public void onStart(Intent intent, int startId) {
    }

	/**
     * Called by the system every time a client explicitly starts the service by calling 
     * {@link android.content.Context#startService}, providing the arguments it supplied and a 
     * unique integer token representing the start request.  Do not call this method directly.
     * 
     * <p>For backwards compatibility, the default implementation calls
     * {@link #onStart} and returns either {@link #START_STICKY}
     * or {@link #START_STICKY_COMPATIBILITY}.
     * 
     * <p>If you need your application to run on platform versions prior to API
     * level 5, you can use the following model to handle the older {@link #onStart}
     * callback in that case.  The <code>handleCommand</code> method is implemented by
     * you as appropriate:
     * 
     * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
     *   start_compatibility}
     *
     * <p class="caution">Note that the system calls this on your
     * service's main thread.  A service's main thread is the same
     * thread where UI operations take place for Activities running in the
     * same process.  You should always avoid stalling the main
     * thread's event loop.  When doing long-running operations,
     * network calls, or heavy disk I/O, you should kick off a new
     * thread, or use {@link android.os.AsyncTask}.</p>
     *
     * @param intent The Intent supplied to {@link android.content.Context#startService}, 
     * as given.  This may be null if the service is being restarted after
     * its process has gone away, and it had previously returned anything
     * except {@link #START_STICKY_COMPATIBILITY}.
     * @param flags Additional data about this start request.
     * @param startId A unique integer representing this specific request to 
     * start.  Use with {@link #stopSelfResult(int)}.
     * 
     * @return The return value indicates what semantics the system should
     * use for the service's current started state.  It may be one of the
     * constants associated with the {@link #START_CONTINUATION_MASK} bits.
     * 
     * @see #stopSelfResult(int)
     */
    public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
        onStart(intent, startId);
        return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
    }

           

啟動服務時依次執行onCreate,onStartCommand,onStart;如果在系統顯示調用stopService和stopSelf之前終止服務,service再次重新開機,onStartCommand會被調用,重新開機服務時依次執行onStartCommand,onStart。無論何時,都會先調用onStartCommand(),在調用onStart()。

onStartCommand傳回值

onStartComand使用時,傳回的是一個(int)整形。

當Android面臨記憶體匮乏的時候,可能會銷毀掉你目前運作的Service,然後待記憶體充足的時候可以重新建立Service,Service被Android系統強制銷毀并再次重建的行為依賴于Service中onStartCommand方法的傳回值。我們常用的傳回值有三種值,START_NOT_STICKY、START_STICKY和START_REDELIVER_INTENT,START_STICKY_COMPATIBILITY,這三個值都是Service中的靜态常量。

1):START_NOT_STICKY:

如果傳回START_NOT_STICKY,表示當Service運作的程序被Android系統強制殺掉之後,不會重新建立該Service,當然如果在其被殺掉之後一段時間又調用了startService,那麼該Service又将被執行個體化。那什麼情境下傳回該值比較恰當呢?如果我們某個Service執行的工作被中斷幾次無關緊要或者對Android記憶體緊張的情況下需要被殺掉且不會立即重新建立這種行為也可接受,那麼我們便可将 onStartCommand的傳回值設定為START_NOT_STICKY。舉個例子,某個Service需要定時從伺服器擷取最新資料:通過一個定時器每隔指定的N分鐘讓定時器啟動Service去擷取服務端的最新資料。當執行到Service的onStartCommand時,在該方法内再規劃一個N分鐘後的定時器用于再次啟動該Service并開辟一個新的線程去執行網絡操作。假設Service在從伺服器擷取最新資料的過程中被Android系統強制殺掉,Service不會再重新建立,這也沒關系,因為再過N分鐘定時器就會再次啟動該Service并重新擷取資料。

2):START_STICKY:

如果傳回START_STICKY,表示Service運作的程序被Android系統強制殺掉之後,Android系統會将該Service依然設定為started狀态(即運作狀态),但是不再儲存onStartCommand方法傳入的intent對象,然後Android系統會嘗試再次重新建立該Service,并執行onStartCommand回調方法,但是onStartCommand回調方法的Intent參數為null,也就是onStartCommand方法雖然會執行但是擷取不到intent資訊。如果你的Service可以在任意時刻運作或結束都沒什麼問題,而且不需要intent資訊,那麼就可以在onStartCommand方法中傳回START_STICKY,比如一個用來播放背景音樂功能的Service就适合傳回該值。

3):START_REDELIVER_INTENT:

如果傳回START_REDELIVER_INTENT,表示Service運作的程序被Android系統強制殺掉之後,與傳回START_STICKY的情況類似,Android系統會将再次重新建立該Service,并執行onStartCommand回調方法,但是不同的是,Android系統會再次将Service在被殺掉之前最後一次傳入onStartCommand方法中的Intent再次保留下來并再次傳入到重新建立後的Service的onStartCommand方法中,這樣我們就能讀取到intent參數。隻要傳回START_REDELIVER_INTENT,那麼onStartCommand重的intent一定不是null。如果我們的Service需要依賴具體的Intent才能運作(需要從Intent中讀取相關資料資訊等),并且在強制銷毀後有必要重新建立運作,那麼這樣的Service就适合傳回START_REDELIVER_INTENT。

4):START_STICKY_COMPATIBILITY:

START_STICKY的相容版本,但不保證服務被kill後一定能重新開機。