最近項(xiàng)目開發(fā)中遇到一個(gè)怪象:在設(shè)置中將app已獲取的location權(quán)限關(guān)閉后忙芒,app進(jìn)程被殺死朝群,通過守護(hù)進(jìn)程重新啟動(dòng)app主進(jìn)程并同時(shí)啟動(dòng)后臺(tái)服務(wù)Service饮醇,此時(shí)app進(jìn)程很快就啟動(dòng)硕蛹,但是Service只是執(zhí)行了onCreat沒有進(jìn)一步執(zhí)行onStartCommand岸更。且在啟動(dòng)Service時(shí)偶現(xiàn)ANR鸵膏。針對(duì)該象限做一下研究分析:
關(guān)閉location權(quán)限關(guān)閉后,app進(jìn)程被殺
- Android已授權(quán)的app怎炊,手動(dòng)在設(shè)置中取消某個(gè)授權(quán)谭企,該app主進(jìn)程會(huì)被殺死,這是Android系統(tǒng)機(jī)制评肆。
Service啟動(dòng)只執(zhí)行onCreat沒有執(zhí)行onStartCommand
- 出現(xiàn)該現(xiàn)象原因是:在守護(hù)闭椋活進(jìn)程中啟動(dòng)Service時(shí),由于出現(xiàn)ANR而將啟動(dòng)執(zhí)行放到Thread中執(zhí)行導(dǎo)致的糟港。將執(zhí)行邏輯從Thread中移出來即可解決該現(xiàn)象攀操。【但是經(jīng)驗(yàn)證單純將Service啟動(dòng)放到Thread中執(zhí)行是正常的】雖然問題已解決但是這里還沒有定位到到底是什么導(dǎo)致該現(xiàn)象,有大俠知道煩請留言告知秸抚,謝謝
Service與Thread的區(qū)別
對(duì)Service了解后速和,會(huì)發(fā)現(xiàn)它實(shí)現(xiàn)的大部分功能使用Thread也可以解決,并且Thread使用起來比Service方便的多剥汤,那么為什么還需要使用Service呢颠放,下面來詳細(xì)解釋一下。
首先吭敢,Thread是程序執(zhí)行的最小單元碰凶,它是分配系統(tǒng)資源的基本單位,主要用于執(zhí)行一些異步的操作鹿驼。而Service是Android的一種機(jī)制欲低,當(dāng)它使用bindService()被綁定的時(shí)候,是運(yùn)行在宿主主進(jìn)程的主線程上的畜晰,當(dāng)使用startService()啟動(dòng)服務(wù)的時(shí)候砾莱,是獨(dú)立運(yùn)行在獨(dú)立進(jìn)程的主線程上的,因此它們的核心沒有任何關(guān)系凄鼻。
其次腊瑟,對(duì)于Thread而言,它是獨(dú)立于啟動(dòng)它的組件的块蚌,如使用一個(gè)Activity啟動(dòng)了一個(gè)Thread闰非,當(dāng)這個(gè)Activity被銷毀前,沒有主動(dòng)停止Thread或者Thread的run()方法沒有執(zhí)行完畢的話峭范,Thread也會(huì)一直執(zhí)行下去财松,這樣就很容易導(dǎo)致一些問題,當(dāng)這個(gè)Activity被銷毀之后纱控,將不再持有這個(gè)Thread的引用辆毡,也就是說政敢,無法再在另外一個(gè)Activity中對(duì)同一個(gè)Thread進(jìn)行控制。而Service不同胚迫,在Android系統(tǒng)中,無論啟動(dòng)或綁定幾次唾那,只會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)的Service實(shí)例访锻,所以只要這個(gè)Service在運(yùn)行,就可以在能獲取到Context對(duì)象的地方控制它闹获,這些特點(diǎn)是Thread無法做到的期犬。
JobService與Service
對(duì)比角度 | Service | JobService | 補(bǔ)充 |
---|---|---|---|
實(shí)現(xiàn)原理 | 由APP側(cè)發(fā)出請求,ActivityManagerService接收請求后進(jìn)行調(diào)度避诽,通知APP側(cè)進(jìn)行創(chuàng)建龟虎,開始(綁定),停止(解綁)和銷毀Service沙庐。 | 由APP側(cè)發(fā)出請求鲤妥,JobSchedulerService接收請求后,通過ActivityManagerService去調(diào)度JobService的創(chuàng)建拱雏,綁定和解綁棉安。并由JobSchedulerService自己進(jìn)行JobService的開始,取消和停止等操作铸抑。 從原理上看贡耽,JobService的開始,取消和停止是由JobSchedulerService維護(hù)的鹊汛,而不是由ActivityManagerService維護(hù)的蒲赂。這是他們在實(shí)現(xiàn)原理上的明顯區(qū)別。即JobService是由系統(tǒng)負(fù)責(zé)調(diào)用和維護(hù) | |
啟動(dòng)條件 | Service的啟動(dòng)并沒有什么特定的條件設(shè)置刁憋。如果說非要有什么具體的執(zhí)行條件的話滥嘴,就是APP側(cè)自己根據(jù)業(yè)務(wù)邏輯在適當(dāng)?shù)臅r(shí)候調(diào)用startService()或者bindService()。 | JobService的執(zhí)行需要至少一個(gè)條件职祷。沒有條件的JobService是無法啟動(dòng)的氏涩,在創(chuàng)建JobInfo的時(shí)候會(huì)拋出異常。 | |
運(yùn)行時(shí)間 | onStartCommand()的回調(diào)在UI線程有梆,不可執(zhí)行耗時(shí)邏輯是尖,否則可能造成ANR。 | onStartJob()的回調(diào)在UI線程泥耀,不可執(zhí)行耗時(shí)邏輯饺汹,否則可能造成ANR或者Job被強(qiáng)制銷毀(超過8s)。并且痰催,JobService里即便新起了線程兜辞,處理的時(shí)間也不能超過10min迎瞧,否則Job將被強(qiáng)制銷毀。 | |
啟動(dòng)角度 | onStartCommand()里返回START_STICKY可以告訴AMS在被停止后自動(dòng)啟動(dòng)逸吵。 | onStopJob()里返回true凶硅,即可在被強(qiáng)制停止后再度啟動(dòng)起來。 | |
擴(kuò)展性 | APP側(cè)可以通過Binder創(chuàng)建遠(yuǎn)程Service進(jìn)行IPC扫皱。 | JobService的綁定實(shí)際上是由JobSchedulerService自己去做的足绅。綁定后產(chǎn)生的Binder用于和JobSchedulerService進(jìn)行IPC,APP側(cè)無法通過JobService擴(kuò)展去實(shí)現(xiàn)別的IPC功能韩脑。 | Google本來的初衷也不是讓JobService實(shí)現(xiàn)遠(yuǎn)程Service的功能氢妈。 |
實(shí)際應(yīng)用上 | 適合需要常駐后臺(tái),立即執(zhí)行段多,進(jìn)行數(shù)據(jù)獲取首量,功能維持的場景。比如 音樂播放进苍,定位加缘,郵件收發(fā)等。 | 適合不需要常駐后臺(tái)琅捏,不需要立即執(zhí)行生百,在某種條件下觸發(fā),執(zhí)行簡單任務(wù)的場景柄延。比如 聯(lián)系人信息變化后的快捷方式的更新蚀浆,定期的更新電話程序的聯(lián)系人信息,壁紙更改后去從壁紙?zhí)崛☆伾暮笈_(tái)任務(wù)搜吧。 |
簡單來講市俊,Service適合一些優(yōu)先級(jí)較高,執(zhí)行任務(wù)復(fù)雜耗時(shí)的任務(wù)滤奈。JobService適合輕量級(jí)的靈活的任務(wù)摆昧。
參考內(nèi)容:
https://www.catbro.cn/detail/5c394d0584063683a872a591.html