Android源碼分析--Service的啟動(dòng)和綁定

Service的啟動(dòng)過程

Service的啟動(dòng)和根Activity的啟動(dòng)很類似。Service的啟動(dòng)同樣需要保證該應(yīng)用程序的進(jìn)程已經(jīng)被啟動(dòng)。

啟動(dòng)大綱

  1. ContextImpl請(qǐng)求AMS啟動(dòng)Service.

  2. AMS請(qǐng)求ActivityThread啟動(dòng)Service.


ContextImpl請(qǐng)求AMS啟動(dòng)Service

在這里插入圖片描述
  • 當(dāng)我們需要啟動(dòng)一個(gè)Service時(shí),我們會(huì)使用context.startService。而Context只是一個(gè)抽象的類,它的實(shí)現(xiàn)是在ContextWrapper中。

  • 在ContextWrapper的startService方法中,又會(huì)調(diào)用其內(nèi)部的Context類型的mBase變量,而該變量的創(chuàng)建詳見ActivityThreadcreateBaseContextForActivity方法,它的實(shí)現(xiàn)類是ContextImpl

  • ContextImplstartService方法中,又會(huì)調(diào)用其自身的startServiceCommon方法。

  • ContextImplstartServiceCommon方法中,會(huì)使用ActivityManager獲取AMS的代理IActivityManager,并調(diào)用其startService方法。

AMS請(qǐng)求ActivityThread啟動(dòng)Service

在這里插入圖片描述
  • AMSstartService方法中調(diào)用ActiveServicestartServiceLocked方法,其中調(diào)用retrieveServiceLocked用于獲取啟動(dòng)服務(wù)的Intent參數(shù)所對(duì)應(yīng)的ServiceRecord,它主要用于描述一個(gè)Service,啟動(dòng)Service所必須的參數(shù)。

  • 在ActiveService的startServiceLocked方法中獲取到相應(yīng)的ServiceRecord之后,就會(huì)調(diào)用其自身的startServiceInnerLocked方法,而它又會(huì)去調(diào)用bringUpServiceLocked方法。在bringUpServiceLocked方法中主要做了以下三個(gè)工作:

(1)獲取Service運(yùn)行所在的進(jìn)程。

(2)如果Service運(yùn)行所在的應(yīng)用程序進(jìn)程ProcessRecord存在,則調(diào)用其自身的realStartServiceLocked方法來啟動(dòng)Service.

(3)如果Service運(yùn)行所在的應(yīng)用程序進(jìn)程ProcessRecord不存在,則需要調(diào)用AMS的startProcessLocked方法來啟動(dòng)應(yīng)用程序進(jìn)程。

  • ActiveServicerealStartServiceLocked方法中,會(huì)使用ProcessRecordIApplicationThread類型的引用(實(shí)現(xiàn)類是ActivityThread的內(nèi)部類ApplicationThread),調(diào)用其scheduleCreateService方法。

  • 在ActivityThread的scheduleCreateService方法中,會(huì)向其內(nèi)部類并繼承自Handler的H發(fā)送CREATE_SERVICE消息,并由H進(jìn)行處理,最終會(huì)調(diào)用handleCreateService方法。

  • ActivityThreadhandleCreateService方法中主要做了如下幾件事:

(1)獲取要啟動(dòng)Service的應(yīng)用程序的LoadApk(包信息),并通過它獲取類的加載器,通過反射創(chuàng)建Service的實(shí)例。

(2)調(diào)用ContextImplcreateAppContext方法,為Service創(chuàng)建上下文環(huán)境ContextImpl對(duì)象。

(3)調(diào)用Serviceattach方法,對(duì)Service進(jìn)行初始化。

(4)調(diào)用ServiceonCreate方法,這樣Service就啟動(dòng)了。


Service的綁定過程

除了使用Context的startService來啟動(dòng)Service外,我們也可以通過Context的bindService來綁定Service。綁定Service的過程要比啟動(dòng)Service的過程復(fù)雜一些。

啟動(dòng)大綱

  1. ContextImpl請(qǐng)求AMS綁定Service.

  2. AMS請(qǐng)求ActivityThread處理Service綁定.

  3. AMS進(jìn)行Service的綁定.


ContextImpl請(qǐng)求AMS綁定Service

在這里插入圖片描述
  • 當(dāng)我們需要綁定一個(gè)Service時(shí),我們會(huì)使用context.bindService。而Context只是一個(gè)抽象的類,它的實(shí)現(xiàn)是在ContextWrapper中。

  • 在ContextWrapper的bindService方法中,又會(huì)調(diào)用其內(nèi)部的Context類型的mBase變量,而該變量的創(chuàng)建詳見ActivityThreadcreateBaseContextForActivity方法,它的實(shí)現(xiàn)類是ContextImpl

  • ContextImplbindService方法中,又會(huì)調(diào)用其自身的bindServiceCommon方法。

  • ContextImplbindServiceCommon方法中,首先調(diào)用LoadedApkgetServiceDispatcher方法獲取ServiceConnection的封裝類(本地的代理)IServiceConnection(用于跨進(jìn)程通信),然后使用ActivityManager獲取AMS的代理IActivityManager,調(diào)用其bindService方法并將IServiceConnection對(duì)象傳入。

AMS請(qǐng)求ActivityThread處理Service綁定

在這里插入圖片描述
  • AMSbindService方法中調(diào)用方法中調(diào)用ActiveServicebindServiceLocked方法,其中同樣的和startServiceLocked一樣調(diào)用retrieveServiceLocked用于獲取啟動(dòng)服務(wù)的Intent參數(shù)所對(duì)應(yīng)的ServiceRecord,然后調(diào)用ServiceRecordretrieveAppBindingLocked方法來獲取應(yīng)用和服務(wù)的綁定信息AppBindRecord,最后調(diào)用requestServiceBindingLocked方法,將之前獲取的AppBindRecord信息傳入,來發(fā)出服務(wù)綁定的請(qǐng)求。

  • 除此之外,在bindServiceLocked方法調(diào)用requestServiceBindingLocked請(qǐng)求綁定前,還調(diào)用了bringUpServiceLocked方法去啟動(dòng)服務(wù)。

  • ActiveServicerequestServiceBindingLocked方法中最終會(huì)調(diào)用ActivityThreadscheduleBindService方法,然后封裝BindServiceData數(shù)據(jù)并將其傳入sendMessage方法中,向H發(fā)送BIND_SERVICE消息。在H對(duì)應(yīng)的消息處理中會(huì)調(diào)用handleBindService方法。在handleBindService方法中,對(duì)未綁定服務(wù)的,先后調(diào)用Service的onBind方法和AMS的publishService方法;對(duì)已綁定服務(wù)的,先后調(diào)用Service的onRebind方法和AMS的serviceDoneExecuting方法。

在這里插入圖片描述
  • 在AMS的publishService方法中又調(diào)用了ActiveServicepublishServiceLocked方法。

  • publishServiceLocked方法中會(huì)調(diào)用IServiceConnectionconnected方法來建立服務(wù)連接,最終會(huì)調(diào)用執(zhí)行LoadApk中的RunConnection任務(wù),執(zhí)行doConnected方法建立服務(wù)綁定連接。

與Service綁定相關(guān)的對(duì)象類型介紹:

  • ServiceRecord:用于描述一個(gè)Service。

  • ProcessRecord:一個(gè)進(jìn)程所包含的信息。

  • ConnectionRecord:用于描述應(yīng)用程序進(jìn)程和Service建立的一次通信。

  • AppBindRecord: 用于維護(hù)Service與應(yīng)用進(jìn)程之間的綁定信息。

  • IntentBindRecord:用于描述綁定Service的Intent信息。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容