Android Service解析


Android Service是一個可以在后台執行長時間運行操作而不提供用戶界面的應用組件,它分為兩種工作狀態,一種是啟動狀態,主要用於執行后台計算;另一種是綁定狀態,主要用於其他組件和Service的交互。需要注意的兩點:

  • 兩種狀態是共存的,即Service可以是啟動狀態也可以同時是綁定狀態
  • 防止ANR風險,主線程運行的Service在執行耗時操作,則應在服務內創建新線程來完成這項工作,這可以降低發生“應用無響應”(ANR) 錯誤的風險。

使用

要創建服務,您必須創建 Service 的子類。在實現中,需要重寫一些回調方法,以處理服務生命周期的某些關鍵方面並提供一種機制將組件綁定到服務。

public class MyService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Service需要重寫重要的回調方法有以下幾個

  • onStartCommand():通過調用 startService() 請求啟動服務時,系統將調用此方法,bindService無需實現該方法
  • onBind():通過調用 bindService() 與服務綁定(例如執行 RPC)時,系統將調用此方法,通過返回 IBinder 提供一個接口,供客戶端用來與服務進行通信
  • onCreate():首次創建服務時,系統將調用此方法來執行一次性設置程序(在調用 onStartCommand() 或 onBind() 之前)
  • onDestroy():當服務不再使用且將被銷毀時,系統將調用此方法。服務應該實現此方法來清理所有資源,如線程、注冊的偵聽器、接收器等。 這是服務接收的最后一個調用

像Activity(以及其他組件)一樣,您必須在應用AndroidManifest.xml清單文件中聲明所有服務

<service android:name=".MyService"/>

通過Context啟動一個Service,這會導致對 onStartCommand() 的調用,則服務將一直運行,直到服務使用 stopSelf() 自行停止運行,或由其他組件通過調用 stopService() 停止,如下所示

startService(new Intent(this, MyService.class));

但在Android8.0的應用嘗試在不允許其創建后台服務的情況下使用 startService() 函數,則該函數將引發一個 IllegalStateException。 新的 Context.startForegroundService() 函數將啟動一個前台服務。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(intent);
} else {
    startService(intent);
}

並且在在service里再調用startForeground方法,不然就會出現ANR

context.startForeground(SERVICE_ID, builder.getNotification());

通過Context綁定一個Service,且未調用 onStartCommand(),則服務只會在該組件與其綁定時運行,一旦該服務與所有客戶端之間的綁定全部取消,系統便會銷毀它,如下所示

bindService(new Intent(this, MyService.class), connection, BIND_AUTO_CREATE);

注意:系統內存不足時,Android會強制停止優先級低的Service來提供內存給Activity使用,但持有Activity的Service可能不會終止,或者前台運行的Service幾乎永遠不會終止。

Service啟動

首先我們先看下Service的類的調用流程
圖片
相關類說明

  • ContextWrapper:代理Context的實現,簡單地將其所有調用委托給另一個Context
  • ContextImpl:Context API的通用實現,為Activity和其他應用程序組件提供基本上下文對象
  • ActivityManager:此類提供有關活動,服務和包含過程的信息和交互
  • IActivityManager.aidl:用於與ActivityManagerService交談的系統專用API,提供了從應用程序返回到活動管理器的調用
  • ActivityManagerService:負責系統中四大組件的啟動、切換、調度及應用進程的管理和調度等工作
  • ActivityThread:管理應用程序進程中主線程的執行,根據ActivityManager請求調度和執行Activitys、broadcasts和其他操作
  • ApplicationThread:ActivityThread內部類,IApplicationThread.aidl的具體實現,提供給ActivityManager,ActivityManager通過它告知應用程序將要做的事
  • IApplicationThread:用於與應用程序通信的系統專用API

Service最終創建需要需要通過Handler進行消息發送來實現創建,並把創建好的servic存儲在ArrayMap中。接下來看下Service的生命周期是怎樣的。
圖片
需要注意的是,在整個生命周期內,只有startCommand()能被多次調用。其他方法只能被調用一次。

Service綁定

Service綁定跟Service的啟動了類調用流程基本一致,只是相關方法改為bind,但其最后會調用ServiceConnection對象的onServiceConnected方法。接下來看下Service的生命周期是怎樣的
圖片
但其有一個特性,多次綁定同一個Service時,Service的onBind方法只會執行一次,除非Service被終止了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM