Android的Service
- Service是在main Thread中執(zhí)行,Service中不能執(zhí)行耗時操作(網(wǎng)絡請求,拷貝數(shù)據(jù)庫,大文件)。
- 可以在xml中設置Service所在的進程自沧,讓Service在另外的進程中執(zhí)行。
- Service執(zhí)行的操作最多是20s树瞭,BroadcastReceiver是10s拇厢,Activity是5s。
- Activity通過bindService(Intent晒喷,ServiceConnection旺嬉,flag)與Service綁定。
- Activity可以通過startService和bindService啟動Service厨埋。
IntentService
IntentService是一個抽象類邪媳,繼承自Service,內部存在一個ServiceHandler(Handler)和HandlerThread(Thread)荡陷。IntentService是處理異步請求的一個類雨效,在IntentService中有一個工作線程(HandlerThread)來處理耗時操作,啟動IntentService的方式和普通的一樣废赞,不過當執(zhí)行完任務之后徽龟,IntentService會自動停止。另外可以多次啟動IntentService唉地,每一個耗時操作都會以工作隊列的形式在IntentService的onHandleIntent回調中執(zhí)行据悔,并且每次執(zhí)行一個工作線程。IntentService的本質是:封裝了一個HandlerThread和Handler的異步框架耘沼。
生命周期示意圖
Service 作為 Android四大組件之一极颓,應用非常廣泛。和Activity一樣群嗤,Service 也有一系列的生命周期回調函數(shù)菠隆,具體如下圖。
通常,啟動Service有兩種方式骇径,startService和bindService方式躯肌。
startService生命周期
當我們通過調用了Context的startService方法后,我們便啟動了Service破衔,通過startService方法啟動的Service會一直無限期地運行下去清女,只有在外部調用Context的stopService或Service內部調用Service的stopSelf方法時,該Service才會停止運行并銷毀晰筛。
onCreate
onCreate: 執(zhí)行startService方法時校仑,如果Service沒有運行的時候會創(chuàng)建該Service并執(zhí)行Service的onCreate回調方法;如果Service已經(jīng)處于運行中传惠,那么執(zhí)行startService方法不會執(zhí)行Service的onCreate方法。也就是說如果多次執(zhí)行了Context的startService方法啟動Service稻扬,Service方法的onCreate方法只會在第一次創(chuàng)建Service的時候調用一次卦方,以后均不會再次調用。我們可以在onCreate方法中完成一些Service初始化相關的操作泰佳。
onStartCommand
onStartCommand: 在執(zhí)行了startService方法之后盼砍,有可能會調用Service的onCreate方法,在這之后一定會執(zhí)行Service的onStartCommand回調方法逝她。也就是說浇坐,如果多次執(zhí)行了Context的startService方法,那么Service的onStartCommand方法也會相應的多次調用黔宛。onStartCommand方法很重要近刘,我們在該方法中根據(jù)傳入的Intent參數(shù)進行實際的操作,比如會在此處創(chuàng)建一個線程用于下載數(shù)據(jù)或播放音樂等臀晃。
public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
}
當Android面臨內存匱乏的時候觉渴,可能會銷毀掉你當前運行的Service,然后待內存充足的時候可以重新創(chuàng)建Service徽惋,Service被Android系統(tǒng)強制銷毀并再次重建的行為依賴于Service中onStartCommand方法的返回值案淋。我們常用的返回值有三種值,START_NOT_STICKY险绘、START_STICKY和START_REDELIVER_INTENT踢京,這三個值都是Service中的靜態(tài)常量。
START_NOT_STICKY
如果返回START_NOT_STICKY宦棺,表示當Service運行的進程被Android系統(tǒng)強制殺掉之后瓣距,不會重新創(chuàng)建該Service,當然如果在其被殺掉之后一段時間又調用了startService代咸,那么該Service又將被實例化旨涝。那什么情境下返回該值比較恰當呢?如果我們某個Service執(zhí)行的工作被中斷幾次無關緊要或者對Android內存緊張的情況下需要被殺掉且不會立即重新創(chuàng)建這種行為也可接受,那么我們便可將 onStartCommand的返回值設置為START_NOT_STICKY白华。舉個例子慨默,某個Service需要定時從服務器獲取最新數(shù)據(jù):通過一個定時器每隔指定的N分鐘讓定時器啟動Service去獲取服務端的最新數(shù)據(jù)。當執(zhí)行到Service的onStartCommand時弧腥,在該方法內再規(guī)劃一個N分鐘后的定時器用于再次啟動該Service并開辟一個新的線程去執(zhí)行網(wǎng)絡操作厦取。假設Service在從服務器獲取最新數(shù)據(jù)的過程中被Android系統(tǒng)強制殺掉,Service不會再重新創(chuàng)建管搪,這也沒關系虾攻,因為再過N分鐘定時器就會再次啟動該Service并重新獲取數(shù)據(jù)。
START_STICKY
如果返回START_STICKY更鲁,表示Service運行的進程被Android系統(tǒng)強制殺掉之后霎箍,Android系統(tǒng)會將該Service依然設置為started狀態(tài)(即運行狀態(tài)),但是不再保存onStartCommand方法傳入的intent對象澡为,然后Android系統(tǒng)會嘗試再次重新創(chuàng)建該Service漂坏,并執(zhí)行onStartCommand回調方法,但是onStartCommand回調方法的Intent參數(shù)為null媒至,也就是onStartCommand方法雖然會執(zhí)行但是獲取不到intent信息顶别。如果你的Service可以在任意時刻運行或結束都沒什么問題,而且不需要intent信息拒啰,那么就可以在onStartCommand方法中返回START_STICKY驯绎,比如一個用來播放背景音樂功能的Service就適合返回該值。
START_REDELIVER_INTENT
如果返回START_REDELIVER_INTENT谋旦,表示Service運行的進程被Android系統(tǒng)強制殺掉之后剩失,與返回START_STICKY的情況類似,Android系統(tǒng)會將再次重新創(chuàng)建該Service册着,并執(zhí)行onStartCommand回調方法赴叹,但是不同的是,Android系統(tǒng)會再次將Service在被殺掉之前最后一次傳入onStartCommand方法中的Intent再次保留下來并再次傳入到重新創(chuàng)建后的Service的onStartCommand方法中指蚜,這樣我們就能讀取到intent參數(shù)乞巧。只要返回START_REDELIVER_INTENT,那么onStartCommand重的intent一定不是null摊鸡。如果我們的Service需要依賴具體的Intent才能運行(需要從Intent中讀取相關數(shù)據(jù)信息等)绽媒,并且在強制銷毀后有必要重新創(chuàng)建運行,那么這樣的Service就適合返回START_REDELIVER_INTENT免猾。
onBind
Service中的onBind方法是抽象方法是辕,所以Service類本身就是抽象類,也就是onBind方法是必須重寫的猎提,即使我們用不到获三。在通過startService使用Service時,我們在重寫onBind方法時,只需要將其返回null即可疙教。onBind方法主要是用于給bindService方法調用Service時才會使用到棺聊。
onDestroy
onDestroy: 通過startService方法啟動的Service會無限期運行,只有當調用了Context的stopService或在Service內部調用stopSelf方法時贞谓,Service才會停止運行并銷毀限佩,在銷毀的時候會執(zhí)行Service回調函數(shù)。
bindService生命周期
bindService方式啟動Service主要有以下幾個生命周期函數(shù):
onCreate():
首次創(chuàng)建服務時裸弦,系統(tǒng)將調用此方法祟同。如果服務已在運行,則不會調用此方法理疙,該方法只調用一次晕城。
onStartCommand():
當另一個組件通過調用startService()請求啟動服務時,系統(tǒng)將調用此方法窖贤。
onDestroy():
當服務不再使用且將被銷毀時砖顷,系統(tǒng)將調用此方法。
onBind():
當另一個組件通過調用bindService()與服務綁定時主之,系統(tǒng)將調用此方法。
onUnbind():
當另一個組件通過調用unbindService()與服務解綁時李根,系統(tǒng)將調用此方法槽奕。
onRebind():
當舊的組件與服務解綁后,另一個新的組件與服務綁定房轿,onUnbind()返回true時粤攒,系統(tǒng)將調用此方法。