一.基礎(chǔ)知識
1.Service是什么涩哟?
- Service是一個一種在后臺執(zhí)行長時間運行操作而沒有用戶界面的應(yīng)用組件。不能做耗時操作添履。
2.進程
- Service是一種不提供用戶交互頁面但是可以在后臺長時間運行的組件,可以通過在AndroidManifest.xml設(shè)置Service的android:process=":remote"屬性,讓Service運行另一個進程中庄涡,也就是說,雖然你是在當(dāng)前應(yīng)用啟動的這個Service搬设,但是這個Service和這個應(yīng)用并不是同一個進程穴店。
四大組件都支持android:process=":remote"這個屬性撕捍。
因為Service可以運行在不同的進程,這里說一下Android中幾種進程的優(yōu)先級泣洞,當(dāng)系統(tǒng)內(nèi)存不足時候忧风,系統(tǒng)會從優(yōu)先級低的進程開始回收,下面根據(jù)優(yōu)先級由高到低列出Android中幾種進程球凰。
- 前臺進程狮腿,當(dāng)前用戶操作所需要的進程
- 用戶正在交互的Activity(Activity執(zhí)行了onResume方法)
- 與正在交互的Activity綁定的Service
- 設(shè)置為前臺權(quán)限的Service(Service調(diào)用startForeground()方法)
- 正在執(zhí)行某些生命周期回調(diào)的Service,onCreate()弟蚀、onStart()蚤霞、onDestroy()
- 正在執(zhí)行onReceive()的BroadcastReceiver
這種進程基本不會被回收,只有當(dāng)內(nèi)存不足以支持前臺進程同時運行時候义钉,系統(tǒng)才回回收它們昧绣,主要關(guān)注前三個。
- 可見進程捶闸,沒有與用戶交互所必須的組件夜畴,但是在屏幕上仍然可見其內(nèi)容的進程
- 調(diào)用了onPause()方法但仍對用戶可見的Activity
- 與上面這種Activity綁定的Service
- 服務(wù)進程,使用startService()啟動的Service且不屬于上面兩種類別進程的進程删壮,雖然這個進程與用戶交互沒有直接關(guān)系贪绘,但是一般會在后臺執(zhí)行一些耗時操作,所以央碟,只有當(dāng)內(nèi)存不足以維持所有前臺進程和可見進程同時運行税灌,系統(tǒng)才回回收這個類別的進程。
- 后臺進程亿虽,對用戶不可見的Activity進程菱涤,已調(diào)用了onStop()方法的Activity
- 空進程,不包含任何活動應(yīng)用組件的進程洛勉,保留這種進程唯一目的是作為緩存粘秆,縮短引用組件下次啟動時間。通常系統(tǒng)會最優(yōu)先回收這類進程收毫。
此外攻走,一個進程的級別可能會因為其他進程對它的依賴而有所提高,即進程A服務(wù)于進程B(B依賴A)此再,那么A的進程級別至少是和B一樣高的昔搂。
3. Service配置
和其他組件(Activity/ContentProvider/BroadcastReceiver)一樣,Service需要在Androidmanifest.xml中聲明引润。
Service是運行在主線程中的巩趁,如果有什么耗時的操作,建議新建子線程去處理,避免阻塞主線程议慰,降低ANR的風(fēng)險蠢古。
4. 服務(wù)啟動方式
服務(wù)可以由其他組件啟動,而且如果用戶切換到其他應(yīng)用别凹,這個服務(wù)可能會繼續(xù)在后臺執(zhí)行草讶。到目前為止,Android中Service總共有三種啟動方式炉菲。
- Scheduled堕战,可定時執(zhí)行的Service,是Android 5.0(API LEVEL 21)版本中新添加的一個Service拍霜,名為JobService嘱丢,繼承Service類,使用JobScheduler類調(diào)度它并且設(shè)置JobService運行的一些配置祠饺。具體文檔可以參考JobScheduler越驻,如果你的應(yīng)用最低支持版本是21,官方建議使用JobService道偷。
- Started缀旁,通過startService()
啟動的Service。通過這種方式啟動的Service會獨立的運行在后臺勺鸦,即使啟動它的組件已經(jīng)銷毀了并巍。例如Activity A使用startService()啟動了Service B,過了會兒换途,Activity A執(zhí)行onDestroy()被銷毀了懊渡,如果Service B任務(wù)沒有執(zhí)行完畢,它仍然會在后臺執(zhí)行军拟。這種啟動方式啟動的Service需要主動調(diào)用StopService()停止服務(wù)距贷。 - Bound,通過bindService()
啟動的Service吻谋。通過這種方式啟動Service時候,會返回一個客戶端交互接口现横,用戶可以通過這個接口與服務(wù)進行交互漓拾,如果這個服務(wù)是在另一個進程中,那么就實現(xiàn)了進程間通信戒祠,也就是Messenger和AIDL骇两,這個會是下篇文章的重點。多個組件可以同時綁定同一個Service姜盈,如果所有的組件都調(diào)用unbindService()解綁后低千,Service會被銷毀。
startService和bindService可以同時使用
服務(wù)一般分為兩種:
1:本地服務(wù), Local Service 用于應(yīng)用程序內(nèi)部示血。
- 在Service可以調(diào)用Context.startService()啟動棋傍,調(diào)用Context.stopService()結(jié)束。 在內(nèi)部可以調(diào)用Service.stopSelf() 或 Service.stopSelfResult()來自己停止难审。無論調(diào)用了多少次startService()瘫拣,都只需調(diào)用一次 stopService()來停止。
2:遠程服務(wù)告喊, Remote Service 用于android系統(tǒng)內(nèi)部的應(yīng)用程序之間麸拄。
- 可以定義接口并把接口暴露出來,以便其他應(yīng)用進行操作黔姜÷G校客戶端建立到服務(wù)對象的連接,并通過那個連接來調(diào)用服 務(wù)秆吵。調(diào)用Context.bindService()方法建立連接淮椰,并啟動,以調(diào)用 Context.unbindService()關(guān)閉連接帮毁。多個客戶端可以綁定至同一個服務(wù)实苞。如果服務(wù)此時還沒有加載,bindService()會先加 載它烈疚。提供給可被其他應(yīng)用復(fù)用黔牵,比如定義一個天氣預(yù)報服務(wù),提供與其他應(yīng)用調(diào)用即可爷肝。
那么先來看Service的生命周期吧:
context.startService() ->onCreate()- >onStartCommand()->Service running--調(diào)用context.stopService() ->onDestroy()
context.bindService()->onCreate()->onBind()->Service running--調(diào)用>onUnbind() -> onDestroy()
從上訴可以知道分別對應(yīng)本地的猾浦,,以及遠程的灯抛,也對應(yīng)不同的方式啟動這個服務(wù)金赦。
二.注意事項
2.1 同一服務(wù),多次啟動对嚼,服務(wù)實際執(zhí)行的過程
- 第一次 啟動服務(wù)時夹抗,運行 onCreate -->onStartCommand
后面在啟動服務(wù)時,服務(wù)只執(zhí)行onStartCommand纵竖。在實際使用過程中漠烧,通過Intent 傳遞數(shù)據(jù),在OnStartCommand中執(zhí)行靡砌。
具體代碼如下: