Android Service詳解(一)

Service系列一共2篇,主要介紹Service相關的使用,以及使用Service實現IPC通訊。本文的重點是介紹Service相關的使用,經過Service 實現IPC通訊放在下一篇講解。java

What is a Service

根據官方的介紹:app

  1. Service既不是一個線程,Service一般運行在當成宿主進程的主線程中,因此在Service中進行一些耗時操做就須要在Service內部開啓線程去操做,不然會引起ANR異常。
  2. 也不是一個單獨的進程。除非在清單文件中聲明時指定進程名,不然Service所在進程就是application所在進程。

Service存在的目的有2個:異步

  1. 告訴系統,當前程序須要在後臺作一些處理。這意味着,Service能夠不須要UI就在後臺運行,不用管開啓它的頁面是否被銷燬,只要進程還在就能夠在後臺運行。能夠經過startService()方式調用,這裏須要注意,除非Service手動調用stopService()或者Service內部主動調用了stopSelf(),不然Service一直運行。
  2. 程序經過Service對外開放某些操做。經過bindService()方式與Service調用,長期鏈接和交互,Service生命週期和其綁定的組件相關。

Service Lifecycle

public class MyService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return startCommandReturnId;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
複製代碼

要解釋這個首先要知道Service的實現,須要實現抽象方法onBind,以及重寫onStartCommand,這2個方法會在下文介紹到。ide

經過上面的介紹能夠知道,Service有3種啓動方式:oop

  1. startService()
  2. bindService()
  3. 同時調用

這幾種方式啓動的Service生命週期略微不一樣。post

startService方式

startService()只要一個Intent參數,指定要開啓的Service便可this

Intent intent = new Intent(MainActivity.this, MyService.class);
複製代碼
  1. 當調用Service的startService()後,spa

    • Service首次啓動,則先調用onCreate(),在調用onStartCommand()
    • Service已經啓動,則直接調用onStartCommand()
  2. 當調用stopSelf()或者stopService()後,會執行onDestroy(),表明Service生命週期結束。線程

  3. startService方式啓動Service不會調用到onBind()。 startService能夠屢次調用,每次調用都會執行onStartCommand()。 無論調用多少次startService,只須要調用一次stopService就結束。 若是startService後沒有調用stopSelf或者stopService,則Service一直存活並運行在後臺。code

  4. onStartCommand的返回值一共有3種

    • START_STICKY = 1:service所在進程被kill以後,系統會保留service狀態爲開始狀態。系統嘗試重啓service,當服務被再次啓動,傳遞過來的intent可能爲null,須要注意。
    • START_NOT_STICKY = 2:service所在進程被kill以後,系統再也不重啓服務
    • START_REDELIVER_INTENT = 3:系統自動重啓service,並傳遞以前的intent

    默認返回START_STICKY;

bindService方式

經過bindService綁定Service相對startService方式要複雜一點。 因爲bindService是異步執行的,因此須要額外構建一個ServiceConnection對象用與接收bindService的狀態,同時還要指定bindService的類型。

//1. 定義用於通訊的對象,在Service的onBind()中返回的對象。
public class MyBind extends Binder {
        public int mProcessId;
 }

//2. 定義用於接收狀體的ServiceConnection
mServiceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                //和服務綁定成功後,服務會回調該方法
                //服務異常中斷後重啓,也會從新調用改方法
                MyService.MyBind myBinder = (MyService.MyBind) service;
            }

            @Override
            public void onNullBinding(ComponentName name) {
                //Service的onBind()返回null時將會調用這個方法,並不會調用onServiceConnected()
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                // 當服務異常終止時會調用。
                // 注意,unbindService時不會調用
            }
        };
        
//3. 在須要的地方綁定到Service
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
複製代碼

bindService()也能夠調用屢次,與startService()不一樣,當發起對象與Service已經成功綁定後,不會屢次返回ServiceConnection中的回調方法。

經過bindService方式與Service進行綁定後,當沒有對象與Service綁定後,Service生命週期結束,這個過程包括綁定對象被銷燬,或者主動掉調用unbindService()

startService和bindService同時開啓

當同時調用startService和bindService後,須要分別調用stopService和unbindService,Service纔會走onDestroy()

一個Service必需要在既沒有和任何Activity關聯又處理中止狀態的時候纔會被銷燬。

IntentService

經過上面的介紹咱們知道,經過StartService形式開啓Service時,若是不主動調用stopService,Service將在後臺一直運行。同時若是咱們在Service中執行耗時操做仍是引發ANR異常,爲了解決這2個問題,IntentService出現了。 當咱們須要執行某些一次性、異步的操做時,IntentService能很好的知足這個場景。

IntentService相比於普通的Service,在使用時將再也不須要實現onStartCommand(),同時須要實現onHandleIntent()。 真正須要咱們處理的邏輯就在onHandleIntent()實現,IntentService會內部自動調用stopSelf()關閉本身。

至於防止ANR異常,具體的實現方式其實仍是挺簡單,就是在內部新建了子線程,並在子線程中內部的Looper來分發事件,具體代碼就不貼了。

下一篇Android Service詳解(二)將介紹經過Service實現IPC通訊

相關文章
相關標籤/搜索