(十)Service
Service有兩套流程,一套是啟動流程,另一套是綁定流程。我們做App開發的同學都應該知道。

1)在新程序啟動Service
我們先看Service啟動過程,假設要啟動的Service是在一個新的程序中,分為5個階段:
1)App向AMS發送一個啟動Service的消息。
2)AMS檢查啟動Service的程序是否存在,如果不存在,先把Service資訊存下來,然後建立一個新的程序。
3)新程序啟動後,通知AMS說我可以啦。
4)AMS把剛才儲存的Service資訊發送給新程序
5)新程序啟動Service
我們仔細看一下這5個階段:
第1階段
和Activity非常像,仍然是通過AMM/AMP把要啟動的Service資訊發送給AMS。
第2階段
AMS檢查Service是否在Manifest中聲明了,沒聲明會直接報錯。
AMS檢查啟動Service的程序是否存在,如果不存在,先把Service資訊存下來,然後建立一個新的程序。
在AMS中,每個Service,都使用ServiceRecord對象來儲存。
第3階段
Service所在的新程序啟動的過程,就和前面介紹App啟動時的過程差不多。
新程序啟動後,也會建立新的ActivityThread,然後把ActivityThread對象通過AMP傳遞給AMS,告訴AMS,新程序啟動成功了。
第4階段
AMS把傳進來的ActivityThread對象改造為ApplicationThreadProxy,也就是ATP,通過ATP,把要啟動的Service資訊發送給新程序。
第5階段
新程序通過ApplicationThread接收到AMS的資訊,和前面介紹的啟動Activity的最後一步相同,借助于ActivityThread和H,執行Service的onCreate方法。在此期間,為Service建立了Context上下文對象,并與Service相關聯。
需要重點關注的是ActivityThread的handleCreateService方法,
你會發現,這段代碼和前面介紹的handleLaunchActivity差不多,都是從PMS中取出包的資訊packageInfo,這是一個LoadedApk對象,然後擷取它的classloader,反射出來一個類的對象,在這裡反射的是Service。
四大元件的邏輯都是如此,是以我們要做插件化,可以在這裡做文章,換成插件的classloader,加載插件中的四大元件。
至此,我們在一個新的程序中啟動了一個Service。
2)啟動統一程序的Service
如果是在目前程序啟動這個Service,那麼上面的步驟就簡化為:
2)AMS例行檢查,比如Service是否聲明了,把Service在AMS這邊注冊。AMS發現要啟動的Service就是App所在的Service,就通知App啟動這個Service。
3)App啟動Service。
我們看到,沒有了啟動新程序的過程。
3)在同一程序綁定Service
如果是在目前程序綁定這個Service呢?過程是這樣的:
1)App向AMS發送一個綁定Service的消息。
2)AMS例行檢查,比如Service是否聲明了,把Service在AMS這邊注冊。AMS發現要啟動的Service就是App所在的Service,就先通知App啟動這個Service,然後再通知App,對Service進行綁定操作。
3)App收到AMS第1個消息,啟動Service,
4)App收到AMS第2個消息,綁定Service,并把一個Binder對象傳給AMS
5)AMS把接收到的Binder對象,發送給App
6)App收到Binder對象,就可以使用了。
你也許會問,都在一個程序,App内部直接使用Binder對象不就好了,其實吧,要考慮不在一個程序的場景,代碼又不能寫兩份,兩套邏輯,是以就都放在一起了,即使在同一個程序,也要繞着AMS走一圈。
第1階段:App向AMS發送一個綁定Service的消息。
第4階段:處理第2個消息
第5階段和第6階段:
這一步是要仔細說的,因為AMS把Binder對象傳給App,這裡沒用ATP和APT,而是用到了AIDL來實作,這個AIDL的名字是IServiceConnection。
ServiceDispatcher的connect方法,最終會調用ServiceConneciont的onServiceConnected方法,這個方法我們就很熟悉了。App開發人員在這個方法中拿到connection,就可以做自己的事情了。
好了,關于Service的底層知識,我們就全都介紹完了。當你再去編寫一個Service時,是否感覺對這個元件了解的更透徹了呢?
下一篇我們聊一聊BroadcastReceiver。