Android Service生命周期詳解
引言
應(yīng)用程序組件有一個(gè)生命周期——一開始Android實(shí)例化他們響應(yīng)意圖,直到結(jié)束實(shí)例被銷毀。在這期間,他們有時(shí)候處于激活狀態(tài),有時(shí)候處于非激活狀 態(tài);對(duì)于活動(dòng),對(duì)用戶有時(shí)候可見,有時(shí)候不可見。組件生命周期將討論活動(dòng)、服務(wù)、廣播接收者的生命周期——包括在生命周期中他們可能的狀態(tài)、通知狀態(tài)改變 的方法、及這些狀態(tài)的組件寄宿的進(jìn)程被終結(jié)和實(shí)例被銷毀的可能性。
上篇Android開發(fā)之旅:組件生命周期(一)講解了論活動(dòng)的生命周期及他們可能的狀態(tài)、通知狀態(tài)改變的方法。本篇將介紹服務(wù)和廣播接收者的生命周期:
服務(wù)生命周期
廣播接收者生命周期
1、服務(wù)生命周期
一個(gè)服務(wù)可以用在兩個(gè)方面:
它可以啟動(dòng)且允許一直運(yùn)行直到有人停止它,或者它自己停止。在這種模式,通過調(diào)用Context.startService()啟動(dòng)服務(wù)及通過調(diào)用 Context.stopService()停止服務(wù)。服務(wù)也可以通過調(diào)用Service.stopSelf()或 Service.stopSelfResult()停止自己。僅需要調(diào)用一次stopService()停止服務(wù),而不管調(diào)用 startService()了多少次。
通過使用相關(guān)接口可以編程地操作服務(wù)??蛻舳私⑴cService對(duì)象的一個(gè)連接及使用該連接調(diào)入服務(wù)。連接通過調(diào)用 Context.bindService()建立,通過調(diào)用Context.unbindService()關(guān)閉。多個(gè)客戶端可以綁定到同一個(gè)服務(wù)。如果 服務(wù)尚未啟動(dòng),bindService()可以選擇啟動(dòng)它。
這兩種模式并不是完全分離的。你可以綁定到一個(gè)用startService()啟動(dòng)的服務(wù)。例如,一個(gè)后臺(tái)音樂服務(wù)可以通過使用定義了音樂播放的 Intent對(duì)象調(diào)用startService()啟動(dòng)。直到后來,用戶可能想對(duì)播放器做一些控制或者獲取當(dāng)前歌曲的一些信息,一個(gè)活動(dòng)將調(diào)用 bindService()與服務(wù)建立連接。在這種情況下,實(shí)際上直到最后一個(gè)綁定關(guān)閉stopService()并不會(huì)停止。
像活動(dòng)一樣,一個(gè)服務(wù)也有生命周期方法,你可以執(zhí)行監(jiān)視它的狀態(tài)改變。但是比活動(dòng)的生命周期方法更少,只有三個(gè)且它們是公有的(public)而不是受保護(hù)的(protected)(說明:活動(dòng)的生命周期方法是protected的):
void onCreate()
void onStart(Intent intent)
void onDestory()
通過這三個(gè)方法,你可以監(jiān)視服務(wù)生命周期的兩個(gè)嵌套循環(huán):
服務(wù)的整個(gè)生命時(shí)間(entire lifetime),從調(diào)用onCreate()到相應(yīng)地調(diào)用onDestory()。像一個(gè)活動(dòng)一樣,服務(wù)在onCreate()中做一些初始設(shè)置,且 在中釋放所有的資源。例如,一個(gè)音樂播放服務(wù)可以在onCreate()中創(chuàng)建線程,然后在onDestory()中停止線程。
服務(wù)的活躍生命時(shí)間(active lifetime),從調(diào)用onStart()開始。這個(gè)方法傳遞參數(shù)是傳送給startService()的Intent對(duì)象。音樂服務(wù)將打開Intent,了解播放哪個(gè)音樂并且開始播放。
沒有相應(yīng)的回調(diào)方法,因?yàn)榉?wù)停止沒有onStop()方法。
startService()和onDestory()被所有服務(wù)調(diào)用,不管是通過Context.startService()啟動(dòng)還是通過 Context.bindService()啟動(dòng)的。然而,onStart()僅被通過startService()啟動(dòng)的服務(wù)調(diào)用。
如果一個(gè)服務(wù)允許別的綁定到它,有一些額外的回調(diào)方法來實(shí)現(xiàn)它:
IBinder onBind(Intent intent)
boolean onUnbind(Intent intent)
void onRebind(Intent intent)
onBind()回調(diào)傳遞的參數(shù)是傳給bindService()的Intent對(duì)象,onUnbind()回調(diào)傳遞的參數(shù)是傳給 unbindService()的Intent對(duì)象。如果服務(wù)允許綁定,onBind()返回客戶端與服務(wù)交互的通信通道。onUnbind()方法可以 要求調(diào)用onRebind(),如果一個(gè)新的客戶端連接到服務(wù)。
下圖解釋了服務(wù)的回調(diào)方法。雖然,它分離了由startService()啟動(dòng)的服務(wù)和由bindService()啟動(dòng)的服務(wù),記住任何服務(wù),無論 它怎么啟動(dòng)的,都可能允許客戶端綁定到它,因此任何服務(wù)可能接收onBind()和onUnbind()調(diào)用。
可以發(fā)現(xiàn)第一次startService時(shí),會(huì)調(diào)用onCreate和onStart,在沒有stopService前,無論點(diǎn)擊多少次 startService,都只會(huì)調(diào)用onStart。而stopService時(shí)調(diào)用onDestroy。再次點(diǎn)擊stopService,會(huì)發(fā)現(xiàn)不會(huì) 進(jìn)入service的生命周期的,即不會(huì)再調(diào)用onCreate,onStart和onDestroy。
而onBind在startService/stopService中沒有調(diào)用。
需要注意一個(gè)問題,當(dāng)Activity退出的時(shí)候,Sercvice并不會(huì)停止,此時(shí)我們可以再進(jìn)入Activity重新綁定,當(dāng)這時(shí)候Service 就會(huì)調(diào)用onRebind()方法,但是調(diào)用onRebind()方法的前提是先前的onUnbind()方法執(zhí)行成功,但是使用 super.onUnbind(intent)是執(zhí)行不成功的,這時(shí)候我們要手動(dòng)的使其返回true,再次綁定時(shí)Rebind()就會(huì)執(zhí)行。否則,如果退 出時(shí)不顯示的指定onUnbind()為成功的話(為false),那么重新啟動(dòng)此Activity來綁定服務(wù)時(shí),Service的onBind()方法 和onReBind都不會(huì)執(zhí)行,但是ServiceConnection方法確一定會(huì)回調(diào)了。這說明在Service中的onBind()方法不同于 onStart()方法不能被重復(fù)調(diào)用。
2、廣播接收者生命周期
一個(gè)廣播接收者有一個(gè)回調(diào)方法:void onReceive(Context curContext, Intent broadcastMsg)。當(dāng)一個(gè)廣播消息到達(dá)接收者是,Android調(diào)用它的onReceive()方法并傳遞給它包含消息的Intent對(duì)象。廣 播接收者被認(rèn)為僅當(dāng)它執(zhí)行這個(gè)方法時(shí)是活躍的。當(dāng)onReceive()返回后,它是不活躍的。
有一個(gè)活躍的廣播接收者的進(jìn)程是受保護(hù)的,不會(huì)被殺死。但是系統(tǒng)可以在任何時(shí)候殺死僅有不活躍組件的進(jìn)程,當(dāng)占用的內(nèi)存別的進(jìn)程需要時(shí)。
這帶來一個(gè)問題,當(dāng)一個(gè)廣播消息的響應(yīng)時(shí)費(fèi)時(shí)的,因此應(yīng)該在獨(dú)立的線程中做這些事,遠(yuǎn)離用戶界面其它組件運(yùn)行的主線程。如果onReceive()衍 生線程然后返回,整個(gè)進(jìn)程,包括新的線程,被判定為不活躍的(除非進(jìn)程中的其它應(yīng)用程序組件是活躍的),將使它處于被殺的危機(jī)。解決這個(gè)問題的方法是 onReceive()啟動(dòng)一個(gè)服務(wù),及時(shí)服務(wù)做這個(gè)工作,因此系統(tǒng)知道進(jìn)程中有活躍的工作在做。
ps:Service 類兩種啟動(dòng)方法:
• Context.startService()
• Context.bindService()
1. 在同一個(gè)應(yīng)用任何地方調(diào)用 startService() 方法就能啟動(dòng) Service 了,然后系統(tǒng)會(huì)回調(diào) Service 類的 onCreate() 以及 onStart() 方法。這樣啟動(dòng)的 Service 會(huì)一直運(yùn)行在后臺(tái),直到 Context.stopService() 或者 selfStop() 方法被調(diào)用。
另外如果一個(gè) Service 已經(jīng)被啟動(dòng),其他代碼再試圖調(diào)用 startService() 方法,是不會(huì)執(zhí)行 onCreate() 的,但會(huì)重新執(zhí)行一次 onStart() 。
2. 另外一種 bindService() 方法的意思是,把這個(gè) Service 和調(diào)用 Service 的客戶類綁起來,如果調(diào)用這個(gè)客戶類被銷毀,Service 也會(huì)被銷毀。用這個(gè)方法的一個(gè)好處是,bindService() 方法執(zhí)行后 Service 會(huì)回調(diào)上邊提到的 onBind() 方發(fā),你可以從這里返回一個(gè)實(shí)現(xiàn)了 IBind 接口的類,在客戶端操作這個(gè)類就能和這個(gè)服務(wù)通信了,比如得到 Service 運(yùn)行的狀態(tài)或其他操作。如果 Service 還沒有運(yùn)行,使用這個(gè)方法啟動(dòng) Service 就會(huì) onCreate() 方法而不會(huì)調(diào)用 onStart()。
總結(jié):
1. startService()的目的是回調(diào)onStart()方法,onCreate() 方法是在Service不存在的時(shí)候調(diào)用的,如果Service存在(例如之前調(diào)用了bindService,那么Service的onCreate方法已經(jīng)調(diào)用了)那么startService()將跳過onCreate() 方法。
2. bindService()目的是回調(diào)onBind()方法,它的作用是在Service和調(diào)用者之間建立一個(gè)橋梁,并不負(fù)責(zé)更多的工作(例如一個(gè)Service需要連接服務(wù)器的操作),一般使用bindService來綁定到一個(gè)現(xiàn)有的Service(即通過StartService啟動(dòng)的服務(wù))。
由于Service 的onStart()方法只有在startService()啟動(dòng)Service的情況下才調(diào)用,故使用onStart()的時(shí)候要注意這點(diǎn)。
- Android實(shí)現(xiàn)Activity、Service與Broadcaster三大組件之間互相調(diào)用的方法詳解
- Android Service自啟動(dòng)注意事項(xiàng)分析
- Android中使用Service實(shí)現(xiàn)后臺(tái)發(fā)送郵件功能實(shí)例
- Android實(shí)現(xiàn)從activity中停止Service的方法
- Android編程實(shí)現(xiàn)開始及停止service的方法
- Android getSystemService用法實(shí)例總結(jié)
- Android中Service服務(wù)詳解(二)
- Android中Service服務(wù)詳解(一)
- 詳解Android中IntentService的使用方法
- 詳解Android中Service服務(wù)的基礎(chǔ)知識(shí)及編寫方法
相關(guān)文章
Android實(shí)戰(zhàn)打飛機(jī)游戲之實(shí)現(xiàn)主角以及主角相關(guān)元素(3)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)戰(zhàn)打飛機(jī)游戲之實(shí)現(xiàn)主角以及主角相關(guān)元素,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07Android 拍照并對(duì)照片進(jìn)行裁剪和壓縮實(shí)例詳解
這篇文章主要介紹了Android 拍照并對(duì)照片進(jìn)行裁剪和壓縮實(shí)例詳解的相關(guān)資料,這里提供實(shí)例代碼,需要的朋友可以參考下2017-07-07Android SharedPreferences實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ)功能
這篇文章主要為大家詳細(xì)介紹了Android SharedPreferences實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06Android開發(fā)之ListView的簡(jiǎn)單用法及定制ListView界面操作示例
這篇文章主要介紹了Android開發(fā)之ListView的簡(jiǎn)單用法及定制ListView界面操作,結(jié)合實(shí)例形式分析了Android ListView界面布局相關(guān)操作技巧,需要的朋友可以參考下2019-04-04AndroidImageSlider實(shí)現(xiàn)炫酷輪播廣告效果
這篇文章主要為大家詳細(xì)介紹了AndroidImageSlider實(shí)現(xiàn)炫酷輪播廣告效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08RecyclerView實(shí)現(xiàn)拖拽排序效果
這篇文章主要為大家詳細(xì)介紹了RecyclerView實(shí)現(xiàn)拖拽排序效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06