Service系列問(wèn)題
1.1 注冊(cè)Service需要注意什么
Service還是運(yùn)行在主線程當(dāng)中的尊搬,所以如果需要執(zhí)行一些復(fù)雜的邏輯操作俺夕,最好在服務(wù)的內(nèi)部手動(dòng)創(chuàng)建子線程進(jìn)行處理七蜘,否則會(huì)出現(xiàn)UI線程被阻塞的問(wèn)題
1.2 Service與Activity怎么實(shí)現(xiàn)通信(不要死記硬背万伤,結(jié)合文章)
相關(guān)文章
-
方法一:
- 添加一個(gè)繼承Binder的內(nèi)部類薛躬,并添加相應(yīng)的邏輯方法
- 重寫Service的onBind方法亦鳞,返回我們剛剛定義的那個(gè)內(nèi)部類實(shí)例
- 重寫ServiceConnection,onServiceConnected時(shí)調(diào)用邏輯方法 綁定服務(wù)
-
方法二
- 通過(guò)接口Iservice調(diào)用Service方法迅矛,使用接口調(diào)用service和直接調(diào)用其實(shí)本質(zhì)都是一樣的妨猩,只不過(guò)多了借口一個(gè)步驟
1.3 介紹源碼中Binder機(jī)制(了解)
面試問(wèn)到這個(gè),其實(shí)就是讓你說(shuō)一下binder是干什么的秽褒,Service Manager是如何成為一個(gè)守護(hù)進(jìn)程的
1.4 IntentService與Service的區(qū)別(intentservice的優(yōu)點(diǎn))
IntentService是Service的子類壶硅,是一個(gè)異步的,會(huì)自動(dòng)停止的服務(wù)销斟,很好解決了傳統(tǒng)的Service中處理完耗時(shí)操作忘記停止并銷毀Service的問(wèn)題
- 會(huì)創(chuàng)建獨(dú)立的worker線程來(lái)處理所有的Intent請(qǐng)求庐椒;
- 會(huì)創(chuàng)建獨(dú)立的worker線程來(lái)處理onHandleIntent()方法實(shí)現(xiàn)的代碼,無(wú)需處理多線程問(wèn)題蚂踊;
- 所有請(qǐng)求處理完成后约谈,IntentService會(huì)自動(dòng)停止,無(wú)需調(diào)用stopSelf()方法停止Service;
- 為Service的onBind()提供默認(rèn)實(shí)現(xiàn)窗宇,返回null;
- 為Service的onStartCommand提供默認(rèn)實(shí)現(xiàn)特纤,將請(qǐng)求Intent添加到隊(duì)列中军俊;
- IntentService不會(huì)阻塞UI線程,而普通Serveice會(huì)導(dǎo)致ANR異常
- Intentservice若未執(zhí)行完成上一次的任務(wù)捧存,將不會(huì)新開(kāi)一個(gè)線程粪躬,是等待之前的任務(wù)完成后,再執(zhí)行新的任務(wù)昔穴,等任務(wù)完成后再次調(diào)用stopSelf()
1.5 Service 是否在 main thread 中執(zhí)行, service 里面是否 能執(zhí)行耗時(shí)的操作?
默認(rèn)情況,如果沒(méi)有顯示的指 service 所運(yùn)行的進(jìn)程, Service 和 activity 是運(yùn) 行在當(dāng)前 app 所在進(jìn)程的 main thread(UI 主線程)里面镰官。
service 里面不能執(zhí)行耗時(shí)的操作(網(wǎng)絡(luò)請(qǐng)求,拷貝數(shù)據(jù)庫(kù),大文件 )
特殊情況 ,可以在清單文件配置 service 執(zhí)行所在的進(jìn)程 ,讓 service 在另 外的進(jìn)程中執(zhí)行
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote" >
</service>
1.6 Service的生命周期
Service 有綁定模式和非綁定模式,以及這兩種模式的混合使用方式。不同 的使用方法生命周期方法也不同吗货。
非綁定模式:當(dāng)?shù)谝淮握{(diào)用 startService 的時(shí)候執(zhí)行的方法依次為 onCreate()泳唠、onStartCommand(),當(dāng) Service 關(guān)閉的時(shí)候調(diào)用 onDestory 方 法。
綁定模式:第一次 bindService()的時(shí)候,執(zhí)行的方法為 onCreate()宙搬、 onBind()解除綁定的時(shí)候會(huì)執(zhí)行 onUnbind()笨腥、onDestory()。
上面的兩種生命周期是在相對(duì)單純的模式下的情形勇垛。我們?cè)陂_(kāi)發(fā)的過(guò)程中還 必須注意 Service 實(shí)例只會(huì)有一個(gè),也就是說(shuō)如果當(dāng)前要啟動(dòng)的 Service 已經(jīng)存 在了那么就不會(huì)再次創(chuàng)建該 Service 當(dāng)然也不會(huì)調(diào)用 onCreate()方法脖母。
一個(gè) Service 可以被多個(gè)客戶進(jìn)行綁定,只有所有的綁定對(duì)象都執(zhí)行了
onBind()方法后該 Service 才會(huì)銷毀,不過(guò)如果有一個(gè)客戶執(zhí)行了 onStart() 方法,那么這個(gè)時(shí)候如果所有的 bind 客戶都執(zhí)行了 unBind()該 Service 也不會(huì) 銷毀。
Service 的生命周期圖如下所示,幫助大家記憶闲孤。
只使用startService啟動(dòng)服務(wù)的生命周期
只使用BindService綁定服務(wù)的生命周期
同時(shí)使用startService()啟動(dòng)服務(wù)谆级、BindService()綁定服務(wù)的生命周期
1.7 Activity、Intent讼积、Service 是什么關(guān)系(了解)
他們都是 Android 開(kāi)發(fā)中使用頻率最高的類肥照。其中 Activity 和 Service 都是 Android 四大組件之一。他倆都是 Context 類的子類 ContextWrapper 的子類, 因此他倆可以算是兄弟關(guān)系吧勤众。不過(guò)兄弟倆各有各自的本領(lǐng),Activity 負(fù)責(zé)用戶 界面的顯示和交互,Service 負(fù)責(zé)后臺(tái)任務(wù)的處理建峭。Activity 和 Service 之間可 以通過(guò) Intent 傳遞數(shù)據(jù),因此可以把 Intent 看作是通信使者。
1.8 Service 和 Activity 在同一個(gè)線程嗎决摧?
對(duì)于同一 app 來(lái)說(shuō)默認(rèn)情況下是在同一個(gè)線程中的,main Thread (UI Thread)亿蒸。
1.9 在 service 的生命周期方法 onstartConmand()可不可以執(zhí)行網(wǎng)絡(luò)操作?如何在 service 中執(zhí)行網(wǎng)絡(luò)操作?(在service如何執(zhí)行耗時(shí)操作)
可以直接在 Service 中執(zhí)行網(wǎng)絡(luò)操作,在 onStartCommand()方法中可以執(zhí)行網(wǎng)絡(luò)操作
如果需要在服務(wù)中進(jìn)行耗時(shí)操作,可以選擇IntentService掌桩, IntentService是Service的子類边锁,用來(lái)處理異步請(qǐng)求。
IntentService在onCreate()方法中通過(guò)HandlerThread單獨(dú)開(kāi)啟一個(gè)線程來(lái)處理Intent請(qǐng)求對(duì)象所對(duì)應(yīng)的任務(wù)波岛,這樣可以避免事務(wù)處理阻塞主線程茅坛。
onHandleIntent()函數(shù)針對(duì)Intent的不同進(jìn)行不同的事務(wù)處理就可以,執(zhí)行完一個(gè)Intent請(qǐng)求對(duì)象所對(duì)應(yīng)的工作之后,如果沒(méi)有新的Intent請(qǐng)求達(dá)到贡蓖,則自動(dòng)停止Service曹鸠; 否則ServiceHandler會(huì)取得下一個(gè)Intent請(qǐng)求
傳入該函數(shù)來(lái)處理其所對(duì)應(yīng)的任務(wù)。
2.0 如何提高service的優(yōu)先級(jí)斥铺? (理解彻桃,說(shuō)出兩三條就很nB了)
1、在AndroidManifest.xml文件中對(duì)于intent-filter可以通過(guò)android:priority = “1000”這個(gè)屬性設(shè)置最高優(yōu)先級(jí)晾蜘,1000是最高值邻眷,如果數(shù)字越小則優(yōu)先級(jí)越低,同時(shí)實(shí)用于廣播剔交。
2肆饶、在onStartCommand里面調(diào)用 startForeground()方法把Service提升為前臺(tái)進(jìn)程級(jí)別,然后再onDestroy里面要記得調(diào)用stopForeground ()方法岖常。
3驯镊、onStartCommand方法,手動(dòng)返回START_STICKY竭鞍。
4阿宅、 在onDestroy方法里發(fā)廣播重啟service。
service +broadcast 方式笼蛛,就是當(dāng)service走ondestory的時(shí)候洒放,發(fā)送一個(gè)自定義的廣播,當(dāng)收到廣播的時(shí)候滨砍,重新啟動(dòng)service往湿。(第三方應(yīng)用或是在setting里-應(yīng)用-強(qiáng)制停止時(shí),APP進(jìn)程就直接被干掉了惋戏,onDestroy方法都進(jìn)不來(lái)领追,所以無(wú)法保證會(huì)執(zhí)行)5、監(jiān)聽(tīng)系統(tǒng)廣播判斷Service狀態(tài)响逢。
通過(guò)系統(tǒng)的一些廣播绒窑,比如:手機(jī)重啟、界面喚醒舔亭、應(yīng)用狀態(tài)改變等等監(jiān)聽(tīng)并捕獲到些膨,然后判斷我們的Service是否還存活。6钦铺、Application加上Persistent屬性订雾。
2.1 Service 的 onStartCommand 方法有幾種返回值?各代表什么意思?
有四種返回值,不同值代表的意思如下:
- START_STICKY:如果 service 進(jìn)程被 kill 掉,保留 service 的狀態(tài)為開(kāi)始狀態(tài),但不保留遞送的 intent 對(duì)象。隨 后系統(tǒng)會(huì)嘗試重新創(chuàng)建 service,由于服務(wù)狀態(tài)為開(kāi)始狀態(tài),所以創(chuàng)建服務(wù)后一定會(huì)調(diào)用 onStartCommand(Intent,int,int)方法矛洞。如果在此期間沒(méi)有任何啟動(dòng)命令被傳遞到 service,那么參數(shù) Intent 將為 null洼哎。
- START_NOT_STICKY:“非粘性的”。使用這個(gè)返回值時(shí),如果在執(zhí)行完 onStartCommand 后,服務(wù)被異常 kill 掉,系統(tǒng)不會(huì)自動(dòng)重啟該服務(wù)。
- START_REDELIVER_INTENT:重傳 Intent噩峦。使用這個(gè)返回值時(shí),如果在執(zhí)行完 onStartCommand 后,服務(wù)被異 常 kill 掉,系統(tǒng)會(huì)自動(dòng)重啟該服務(wù),并將 Intent 的值傳入锭沟。
- START_STICKY_COMPATIBILITY: START_STICKY 的兼容版本,但不保證服務(wù)被 kill 后一定能重啟。
2.2 Service 的 onRebind(Intent)方法在什么情況下會(huì)執(zhí)行?
如果在 onUnbind()方法返回 true 的情況下會(huì)執(zhí)行,否則不執(zhí)行识补。
2.3 Activity 調(diào)用 Service 中的方法都有哪些方式?
Binder:
通過(guò) Binder 接口的形式實(shí)現(xiàn),當(dāng) Activity 綁定 Service 成功的時(shí)候 Activity 會(huì)在 ServiceConnection 的類 的 onServiceConnected()回調(diào)方法中獲取到 Service 的 onBind()方法 return 過(guò)來(lái)的 Binder 的子類族淮,然后通過(guò)對(duì)象調(diào)用方法。Aidl:
aidl 比較適合當(dāng)客戶端和服務(wù)端不在同一個(gè)應(yīng)用下的場(chǎng)景李请。Messenger:
它引用了一個(gè)Handler對(duì)象,以便others能夠向它發(fā)送消息(使用mMessenger.send(Message msg)方法)厉熟。該類允許跨進(jìn)程間基于Message的通信(即兩個(gè)進(jìn)程間可以通過(guò)Message進(jìn)行通信)导盅,在服務(wù)端使用Handler創(chuàng)建一個(gè)Messenger,客戶端持有這個(gè)Messenger就可以與服務(wù)端通信了揍瑟。一個(gè)Messeger不能同時(shí)雙向發(fā)送白翻,兩個(gè)就就能雙向發(fā)送了
這里畫了一個(gè)粗淺的圖幫助大家理解。
Service里面可以彈Toast么绢片?
面試經(jīng)驗(yàn):
面試官問(wèn)這個(gè)問(wèn)題就是看看你對(duì)Service是否深入理解滤馍,Service不僅可以彈Toast還能彈出對(duì)話框,把Service看成Activity就行底循,所有的界面都是展示到Window窗體上面的巢株,大家可以回顧下小衛(wèi)士里面來(lái)點(diǎn)歸屬地不就是在服務(wù)里面進(jìn)行監(jiān)聽(tīng)歸屬地進(jìn)行展示的嗎。
答案解析:
可以的熙涤。彈吐司有個(gè)條件就是得有一個(gè)Context上下文阁苞,而Service本身就是Context的子類,因此在Service里面彈Toast是完全可以的祠挫。比如我們?cè)赟ervice中完成下載任務(wù)后可以彈一個(gè)Toast通知用戶那槽。
你一般在什么情況下會(huì)使用Service?
經(jīng)驗(yàn)總結(jié):
Service其實(shí)就是背地搞事情等舔,又不想讓別人知道骚灸,舉一個(gè)生活當(dāng)中的例子,陪女友去做胃鏡慌植,管子才入口十五公分女友就惡心想吐甚牲,那么你就要擔(dān)心了,這婚后日子可咋過(guò)暗痢鳖藕!看完這個(gè),大家應(yīng)該就理解了只锭,你想知道一件事情不需要直接去問(wèn)著恩,你可以通過(guò)側(cè)面了解。這就是Service設(shè)計(jì)的初衷
Service為什么被設(shè)計(jì)出來(lái)?
根據(jù)Service的定義喉誊,我們可以知道需要長(zhǎng)期在后臺(tái)進(jìn)行的工作我們需要將其放在Service中去做邀摆。說(shuō)得再通熟易懂一點(diǎn),就是不能放在Activity中來(lái)執(zhí)行的工作就必須得放到Service中去做伍茄。如:音樂(lè)播放栋盹、下載、上傳大文件敷矫、定時(shí)關(guān)閉應(yīng)用等功能例获。這些功能如果放到Activity中做的話,那Activity退出被銷毀了的話曹仗,那這些功能也就停止了榨汤,這顯然是不符合我們的設(shè)計(jì)要求的,所以要將他們放在Service中去執(zhí)行怎茫。
Activity怎么和service綁定收壕,怎么在activity中啟動(dòng)自己對(duì)應(yīng)的service?
答案解析:
- Activity通過(guò)bindService(Intent service, ServiceConnection conn, int flags)跟Service進(jìn)行綁定轨蛤。
- 綁定成功以后蜜宪,Service會(huì)將代理對(duì)象通過(guò)回調(diào)的形式傳遞給MyServiceConnection,這樣我們就獲取Service提供的代理對(duì)象
- 在Activity中可以通過(guò)startService和bindService方法啟動(dòng)Service祥山。
注意: 如果想獲取Service中提供的代理對(duì)象圃验,那么必須通過(guò)bindService方法,進(jìn)行綁定服務(wù)缝呕。
使用場(chǎng)景比如:音樂(lè)播放器损谦,第三方支付等。
如果僅僅只是為了開(kāi)啟一個(gè)后臺(tái)任務(wù)岳颇,那么可以使用startService方法照捡。