IntentService, Service

Service:

Service其實是運行在主線程裏的;

按使用方式可以分爲以下三種:

1、startService() 啓動的服務:主要用於啓動一個服務執行後臺任務,不進行通信。停止服務使用stopService();

2、bindService() 啓動的服務:該方法啓動的服務可以進行通信。停止服務使用unbindService();

 

1. onStartCommand方式中,返回START_STICKY

首先我們來看看onStartCommand都可以返回哪些值:

調用Context.startService方式啓動Service時,如果Android面臨內存匱乏,可能會銷燬當前運行的Service,待內存充足時可以重建Service。而Service被Android系統強制銷燬並再次重建的行爲依賴於Service的onStartCommand()方法的返回值。

  • 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並重新獲取數據。

  • 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就適合返回該值。

  • 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。

2.提高Service的優先級
在AndroidManifest.xml文件中對於intent-filter可以通過android:priority = "1000"這個屬性設置最高優先級,1000是最高值,如果數字越小則優先級越低,同時適用於廣播。

 

IntentService: 

在 onCreate 中新建 HandlerThread 線程,並完成自身線程looper的創建,

在 onStart 中完成 Message 的創建,併發送給 ServiceHandler 並調用 onHandleIntent 來做具體的處理

在 onHandleIntent 中實現具體邏輯;

如果啓動 IntentService 多次,那麼每一個耗時操作會以工作隊列的方式在 IntentService 的 onHandleIntent 回調方法中執行,依次去執行,使用串行的方式,執行完自動結束。

1.優點
本質上IntentService也是開了一個線程,但是IntentService是繼承自Service的,所以根據Android系統Kill Application的機制,使用IntentService的應用的優先級更高一點。通俗點說如果使用IntentService做後臺任務時,當您的程序退到後臺時,被殺死的機率會更低一點。
既然IntentService是在Service裏開啓線程去做任務處理,那我直接在Service裏啓動線程去做不就好了嗎?當然可以,但是IntentService已經幫您封裝好了,爲什麼還要自己再去實現IntentService的一套邏輯呢?
IntentService會在任務執行完成後自行結束自己,而不需要外部去調用stopService了,適合需要在工作線程處理UI無關任務的場景。

public abstract class IntentService extends Service {

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

    @Override
    public void onCreate() {
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

     @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

}

既然在Service裏也要創建一個子線程,那爲什麼不直接在Activity裏創建呢?這是因爲Activity很難對Thread進行控制,當Activity被銷燬之後,就沒有任何其它的辦法可以再重新獲取到之前創建的子線程的實例;而且在一個Activity中創建的子線程,另一個Activity無法對其進行操作。但是Service就不同了,所有的Activity都可以與Service進行關聯,然後可以很方便地操作其中的方法,即使Activity被銷燬了,之後只要重新與Service建立關聯,就又能夠獲取到原有的Service中Binder的實例。因此,使用Service來處理後臺任務,Activity就可以放心地finish,完全不需要擔心無法對後臺任務進行控制的情況。

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