Service是一個可以在后臺執行長時間運行操作而不使用用戶界面的應用組件。組件可以進行綁定到Service,與之進行交互,甚至可以進行進程間通信(IPC)。
服務形式主要分成兩種:
啟動
應用組件調用startService()方法來啟動Service,Service既可以在后臺無限運行。這種啟動方式是單一的操作,不會將結果進行返回。操作完成后,Service會自動停止。
綁定
當應用組件通過調用 bindService() 綁定到服務時,服務即處于“綁定”狀態。綁定服務提供了一個客戶端-服務器接口,允許組件與服務進行交互、發送請求、獲取結果,甚至是利用進程間通信 (IPC) 跨進程執行這些操作。 僅當與另一個應用組件綁定時,綁定服務才會運行。 多個組件可以同時綁定到該服務,但全部取消綁定后,該服務即會被銷毀。
注意
服務在其托管進程的主線程中運行,它既不創建自己的線程,也不在單獨的進程中運行(除非另行指定)。 這意味著,如果我們在Service中需要進行耗時或者阻塞主線程的操作,需要在Service開啟子線程。通過使用單獨的線程,可以降低發生“應用無響應”(ANR) 錯誤的風險,而應用的主線程仍可繼續專注于運行用戶與 Activity 之間的交互。
基礎知識
主要的回調方法:
- onStartCommand()方法。主要是通過startService來啟動的,并且可以利用Intent進行與組件交互或者傳遞信息。
- onBind()方法。通過bindService()來啟動,在此方法的實現中,您必須通過返回 IBinder 提供一個接口,供客戶端用來與服務進行通信。請務必實現此方法,但如果您并不希望允許綁定,則應返回 null。
- onCreate()方法。無論是啟動形式還是綁定形式,都會調用該方法。并且是第一個調用的回調方法。
- onDestory()方法。主要是用于釋放資源
擴展IntentService類
由于大多數服務都不需要啟動多個請求,所以使用IntentService類會比較簡單
IntentService 執行以下操作:
- 創建默認的工作線程,用于在應用的主線程外執行傳遞給 onStartCommand() 的所有 Intent。
- 創建工作隊列,用于將一個 Intent 逐一傳遞給 onHandleIntent() 實現,這樣您就永遠不必擔心多線程問題。
- 在處理完所有啟動請求后停止服務,因此您永遠不必調用 stopSelf()。
- 提供 onBind() 的默認實現(返回 null)。
- 提供 onStartCommand() 的默認實現,可將 Intent 依次發送到工作隊列和 onHandleIntent() 實現。
綜上所述,您只需實現 onHandleIntent() 來完成客戶端提供的工作即可。(不過,您還需要為服務提供小型構造函數。)
擴展Service類
擴展Service類要看是通過哪種形式來啟動Service。
- 如果是調用startService()方法來啟動,無需去實現onBind()方法,需要去實現onStartCommand()方法。
onStartCommand()方法需要一個整型的返回值。 - 如果是調用bindService()方法,需要去實現onBind()方法,返回一個IBinder接口,用于交互。
停止服務
Service一旦啟動就要管理好生命周期以及內存資源的問題。需要去調用stopSelf()或者stopService()方法來停止服務。
但是,如果服務同時處理多個 onStartCommand() 請求,則您不應在處理完一個啟動請求之后停止服務,因為您可能已經收到了新的啟動請求(在第一個請求結束時停止服務會終止第二個請求)。為了避免這一問題,您可以使用 stopSelf(int) 確保服務停止請求始終基于最近的啟動請求。也就說,在調用 stopSelf(int) 時,傳遞與停止請求的 ID 對應的啟動請求的 ID(傳遞給 onStartCommand() 的 startId) 。然后,如果在您能夠調用 stopSelf(int) 之前服務收到了新的啟動請求, ID 就不匹配,服務也就不會停止。
為了避免浪費系統資源和消耗電池電量,應用必須在工作完成之后停止其服務。 如有必要,其他組件可以通過調用 stopService() 來停止服務。即使為服務啟用了綁定,一旦服務收到對 onStartCommand() 的調用,您始終仍須親自停止服務。