兩種情況得運(yùn)用場(chǎng)景:
1屁奏、用于長(zhǎng)期執(zhí)行某些操作对室,并且甚至與UI(主)線程沒有交互蜡秽。比如啟動(dòng)app直接去網(wǎng)絡(luò)下載文件
2蚤氏、跨進(jìn)程間通信代赁,比如appA程序中Service被appB中程序調(diào)用
注意:Service默認(rèn)時(shí)運(yùn)行在它所在的宿主進(jìn)程的主進(jìn)程中扰她,也就是說如果我們?cè)赟ervice中做耗時(shí)工作,UI(主)線程會(huì)卡死芭碍,出現(xiàn)ARN程序無響應(yīng)現(xiàn)象徒役。為了防止這種情況出現(xiàn),我們一般都是在Service中創(chuàng)建一個(gè)新的線程來處理一些耗時(shí)工作窖壕,這樣就不會(huì)阻塞主線程忧勿。從這里也側(cè)面反映了Service不是另一個(gè)獨(dú)立的進(jìn)程,Service自己本身不會(huì)開辟新的進(jìn)程艇拍,除非手動(dòng)來設(shè)置狐蜕。默認(rèn)情況下,Service是運(yùn)行在本運(yùn)用程序所屬的進(jìn)程中卸夕。
Service啟動(dòng)模式也有兩種层释,分別是:startService和bindService
1、通過startService方式啟動(dòng)
如果運(yùn)行在后臺(tái)的Service甚至不需要和UI(主)線程間進(jìn)行交互快集,這種情況下贡羔,一般是調(diào)用startService來啟動(dòng)Service。
2个初、通過bindService方式啟動(dòng)
兩個(gè)不同進(jìn)程間通信或者某個(gè)應(yīng)用中Service方法的暴露出去(同個(gè)進(jìn)程間)乖寒,一般是調(diào)用bindService來啟動(dòng)Service。
onCreate:如果多次執(zhí)行了Context的startService方法啟動(dòng)Service院溺,Service方法的onCreate方法只會(huì)在第一次創(chuàng)建Service的時(shí)候調(diào)用一次楣嘁,以后均不會(huì)再次調(diào)用。我們可以在onCreate方法中完成一些Service初始化相關(guān)的操作
onStartCommand:如果多次執(zhí)行了Context的startService方法,那么Service的onStartCommand方法也會(huì)相應(yīng)的多次調(diào)用逐虚。onStartCommand方法很重要聋溜,我們?cè)谠摲椒ㄖ懈鶕?jù)傳入的Intent參數(shù)進(jìn)行實(shí)際的操作,比如會(huì)在此處創(chuàng)建一個(gè)線程用于下載數(shù)據(jù)或播放音樂等
onBind:Service中的onBind方法是個(gè)抽象方法叭爱,所以Service類本身就是一個(gè)抽象類撮躁,也就是說onBind方法必須要重寫,即使用不到买雾。通過startService使用Service時(shí)把曼,我們?cè)谥貙憃nBind方法時(shí),只需要將其返回值設(shè)為null即可漓穿。onBind方法主要是用于給bindService方法調(diào)用Service時(shí)才使用到嗤军。
onDestiny:Service銷毀時(shí)回調(diào)函數(shù)
如果Service啟動(dòng)后沒有去停止掉它,它會(huì)一直運(yùn)行下去晃危,停止startService啟動(dòng)的Service有兩種方法:
1型雳、在外部調(diào)用stopService
2、在Service內(nèi)部調(diào)用stopSelf方法
值得注意的是在onStartCommand中返回值山害,常用的返回值有:START_NOT_STICKY纠俭、START_SICKY和START_REDELIVER_INTENT,這三個(gè)都是靜態(tài)常理值。
START_NOT_STICKY:表示當(dāng)Service運(yùn)行的進(jìn)程被Android系統(tǒng)強(qiáng)制殺掉之后浪慌,不會(huì)重新創(chuàng)建該Service冤荆,如果想重新實(shí)例化該Service,就必須重新調(diào)用startService來啟動(dòng)权纤。
使用場(chǎng)景:表示當(dāng)Service在執(zhí)行工作中被中斷幾次無關(guān)緊要或者對(duì)Android內(nèi)存緊張的情況下需要被殺掉且不會(huì)立即重新創(chuàng)建這種行為也可接受的話钓简,這是可以在onStartCommand返回值中設(shè)置該值。如在Service中定時(shí)從服務(wù)器中獲取最新數(shù)據(jù)
START_STICKY:表示Service運(yùn)行的進(jìn)程被Android系統(tǒng)強(qiáng)制殺掉之后汹想,Android系統(tǒng)會(huì)將該Service依然設(shè)置為started狀態(tài)(即運(yùn)行狀態(tài))外邓,但是不再保存onStartCommand方法傳入的intent對(duì)象,然后Android系統(tǒng)會(huì)嘗試再次重新創(chuàng)建該Service古掏,并執(zhí)行onStartCommand回調(diào)方法损话,這時(shí)onStartCommand回調(diào)方法的Intent參數(shù)為null,也就是onStartCommand方法雖然會(huì)執(zhí)行但是獲取不到intent信息槽唾。
使用場(chǎng)景:如果你的Service可以在任意時(shí)刻運(yùn)行或結(jié)束都沒什么問題丧枪,而且不需要intent信息,那么就可以在onStartCommand方法中返回START_STICKY庞萍,比如一個(gè)用來播放背景音樂功能的Service就適合返回該值拧烦。
START_REDELIVER_INTENT:表示Service運(yùn)行的進(jìn)程被Android系統(tǒng)強(qiáng)制殺掉之后,與返回START_STICKY的情況類似钝计,Android系統(tǒng)會(huì)將再次重新創(chuàng)建該Service恋博,并執(zhí)行onStartCommand回調(diào)方法齐佳,但是不同的是,Android系統(tǒng)會(huì)再次將Service在被殺掉之前最后一次傳入onStartCommand方法中的Intent再次保留下來并再次傳入到重新創(chuàng)建后的Service的onStartCommand方法中债沮,這樣我們就能讀取到intent參數(shù)重虑。
使用場(chǎng)景:如果我們的Service需要依賴具體的Intent才能運(yùn)行(需要從Intent中讀取相關(guān)數(shù)據(jù)信息等),并且在強(qiáng)制銷毀后有必要重新創(chuàng)建運(yùn)行秦士,那么這樣的Service就適合返回START_REDELIVER_INTENT。
接著補(bǔ)充一個(gè)知識(shí)點(diǎn)永高,Service進(jìn)一步的封裝類IntentService由于Service是運(yùn)行在UI(主)線程中隧土,會(huì)帶來UI阻塞,所以在操作耗時(shí)工作時(shí)命爬,都在onStartCommand中開啟一個(gè)新的線程去執(zhí)行一些耗時(shí)工作曹傀。正因?yàn)檫@樣,創(chuàng)建一個(gè)帶有工作線程Service是很常見的(因?yàn)楣ぷ骶€程不會(huì)阻塞主線程)梅屉,為了簡(jiǎn)化程序員工作量娃磺,Android額外開發(fā)了一個(gè)類那就是IntentService
IntentService特點(diǎn):
1. IntentService
自帶一個(gè)工作線程沪袭,當(dāng)我們的Service中做一些阻塞UI(主)線程工作時(shí),可以使用IntentService幕庐。
2.將我們實(shí)際要做的工作放入到IntentService的onHandleIntent方法中處理,并且onHandleIntent運(yùn)行在IntentService所持有的工作線程中家淤,而非主線程异剥。
3.當(dāng)多次啟動(dòng)IntentService,產(chǎn)生多個(gè)job絮重,IntentService只能一個(gè)一個(gè)處理冤寿,也就是按照先后順序進(jìn)行處理。先將intent1傳入onHandleIntent青伤,讓其完成job1督怜,然后將intent2傳入onHandleIntent,讓其完成job2…這樣直至所有job完成狠角,所以我們IntentService不能并行地執(zhí)行多個(gè)job号杠,只能一個(gè)一個(gè)的按照先后順序完成,當(dāng)所有job完成的時(shí)候IntentService就銷毀了丰歌,會(huì)執(zhí)行onDestroy回調(diào)方法