Service系列問題
1.1 注冊Service需要注意什么
Service還是運行在主線程當中的,所以如果需要執行一些復雜的邏輯操作,最好在服務的內部手動創建子線程進行處理,否則會出現UI線程被阻塞的問題
1.2 Service與Activity怎么實現通信(不要死記硬背,結合文章)
相關文章
-
方法一:
- 添加一個繼承Binder的內部類,并添加相應的邏輯方法
- 重寫Service的onBind方法,返回我們剛剛定義的那個內部類實例
- 重寫ServiceConnection,onServiceConnected時調用邏輯方法 綁定服務
-
方法二
- 通過接口Iservice調用Service方法,使用接口調用service和直接調用其實本質都是一樣的,只不過多了借口一個步驟
1.3 介紹源碼中Binder機制(了解)
面試問到這個,其實就是讓你說一下binder是干什么的,Service Manager是如何成為一個守護進程的
1.4 IntentService與Service的區別(intentservice的優點)
IntentService是Service的子類,是一個異步的,會自動停止的服務,很好解決了傳統的Service中處理完耗時操作忘記停止并銷毀Service的問題
- 會創建獨立的worker線程來處理所有的Intent請求;
- 會創建獨立的worker線程來處理onHandleIntent()方法實現的代碼,無需處理多線程問題;
- 所有請求處理完成后,IntentService會自動停止,無需調用stopSelf()方法停止Service;
- 為Service的onBind()提供默認實現,返回null;
- 為Service的onStartCommand提供默認實現,將請求Intent添加到隊列中;
- IntentService不會阻塞UI線程,而普通Serveice會導致ANR異常
- Intentservice若未執行完成上一次的任務,將不會新開一個線程,是等待之前的任務完成后,再執行新的任務,等任務完成后再次調用stopSelf()
1.5 Service 是否在 main thread 中執行, service 里面是否 能執行耗時的操作?
默認情況,如果沒有顯示的指 service 所運行的進程, Service 和 activity 是運 行在當前 app 所在進程的 main thread(UI 主線程)里面。
service 里面不能執行耗時的操作(網絡請求,拷貝數據庫,大文件 )
特殊情況 ,可以在清單文件配置 service 執行所在的進程 ,讓 service 在另 外的進程中執行
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote" >
</service>
1.6 Service的生命周期
Service 有綁定模式和非綁定模式,以及這兩種模式的混合使用方式。不同 的使用方法生命周期方法也不同。
非綁定模式:當第一次調用 startService 的時候執行的方法依次為 onCreate()、onStartCommand(),當 Service 關閉的時候調用 onDestory 方 法。
綁定模式:第一次 bindService()的時候,執行的方法為 onCreate()、 onBind()解除綁定的時候會執行 onUnbind()、onDestory()。
上面的兩種生命周期是在相對單純的模式下的情形。我們在開發的過程中還 必須注意 Service 實例只會有一個,也就是說如果當前要啟動的 Service 已經存 在了那么就不會再次創建該 Service 當然也不會調用 onCreate()方法。
一個 Service 可以被多個客戶進行綁定,只有所有的綁定對象都執行了
onBind()方法后該 Service 才會銷毀,不過如果有一個客戶執行了 onStart() 方法,那么這個時候如果所有的 bind 客戶都執行了 unBind()該 Service 也不會 銷毀。
Service 的生命周期圖如下所示,幫助大家記憶。
只使用startService啟動服務的生命周期
只使用BindService綁定服務的生命周期
同時使用startService()啟動服務、BindService()綁定服務的生命周期
1.7 Activity、Intent、Service 是什么關系(了解)
他們都是 Android 開發中使用頻率最高的類。其中 Activity 和 Service 都是 Android 四大組件之一。他倆都是 Context 類的子類 ContextWrapper 的子類, 因此他倆可以算是兄弟關系吧。不過兄弟倆各有各自的本領,Activity 負責用戶 界面的顯示和交互,Service 負責后臺任務的處理。Activity 和 Service 之間可 以通過 Intent 傳遞數據,因此可以把 Intent 看作是通信使者。
1.8 Service 和 Activity 在同一個線程嗎?
對于同一 app 來說默認情況下是在同一個線程中的,main Thread (UI Thread)。
1.9 在 service 的生命周期方法 onstartConmand()可不可以執行網絡操作?如何在 service 中執行網絡操作?(在service如何執行耗時操作)
可以直接在 Service 中執行網絡操作,在 onStartCommand()方法中可以執行網絡操作
如果需要在服務中進行耗時操作,可以選擇IntentService, IntentService是Service的子類,用來處理異步請求。
IntentService在onCreate()方法中通過HandlerThread單獨開啟一個線程來處理Intent請求對象所對應的任務,這樣可以避免事務處理阻塞主線程。
onHandleIntent()函數針對Intent的不同進行不同的事務處理就可以,執行完一個Intent請求對象所對應的工作之后,如果沒有新的Intent請求達到,則自動停止Service; 否則ServiceHandler會取得下一個Intent請求
傳入該函數來處理其所對應的任務。
2.0 如何提高service的優先級? (理解,說出兩三條就很nB了)
1、在AndroidManifest.xml文件中對于intent-filter可以通過android:priority = “1000”這個屬性設置最高優先級,1000是最高值,如果數字越小則優先級越低,同時實用于廣播。
2、在onStartCommand里面調用 startForeground()方法把Service提升為前臺進程級別,然后再onDestroy里面要記得調用stopForeground ()方法。
3、onStartCommand方法,手動返回START_STICKY。
4、 在onDestroy方法里發廣播重啟service。
service +broadcast 方式,就是當service走ondestory的時候,發送一個自定義的廣播,當收到廣播的時候,重新啟動service。(第三方應用或是在setting里-應用-強制停止時,APP進程就直接被干掉了,onDestroy方法都進不來,所以無法保證會執行)5、監聽系統廣播判斷Service狀態。
通過系統的一些廣播,比如:手機重啟、界面喚醒、應用狀態改變等等監聽并捕獲到,然后判斷我們的Service是否還存活。6、Application加上Persistent屬性。
2.1 Service 的 onStartCommand 方法有幾種返回值?各代表什么意思?
有四種返回值,不同值代表的意思如下:
- START_STICKY:如果 service 進程被 kill 掉,保留 service 的狀態為開始狀態,但不保留遞送的 intent 對象。隨 后系統會嘗試重新創建 service,由于服務狀態為開始狀態,所以創建服務后一定會調用 onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到 service,那么參數 Intent 將為 null。
- START_NOT_STICKY:“非粘性的”。使用這個返回值時,如果在執行完 onStartCommand 后,服務被異常 kill 掉,系統不會自動重啟該服務。
- START_REDELIVER_INTENT:重傳 Intent。使用這個返回值時,如果在執行完 onStartCommand 后,服務被異 常 kill 掉,系統會自動重啟該服務,并將 Intent 的值傳入。
- START_STICKY_COMPATIBILITY: START_STICKY 的兼容版本,但不保證服務被 kill 后一定能重啟。
2.2 Service 的 onRebind(Intent)方法在什么情況下會執行?
如果在 onUnbind()方法返回 true 的情況下會執行,否則不執行。
2.3 Activity 調用 Service 中的方法都有哪些方式?
Binder:
通過 Binder 接口的形式實現,當 Activity 綁定 Service 成功的時候 Activity 會在 ServiceConnection 的類 的 onServiceConnected()回調方法中獲取到 Service 的 onBind()方法 return 過來的 Binder 的子類,然后通過對象調用方法。Aidl:
aidl 比較適合當客戶端和服務端不在同一個應用下的場景。Messenger:
它引用了一個Handler對象,以便others能夠向它發送消息(使用mMessenger.send(Message msg)方法)。該類允許跨進程間基于Message的通信(即兩個進程間可以通過Message進行通信),在服務端使用Handler創建一個Messenger,客戶端持有這個Messenger就可以與服務端通信了。一個Messeger不能同時雙向發送,兩個就就能雙向發送了
這里畫了一個粗淺的圖幫助大家理解。
Service里面可以彈Toast么?
面試經驗:
面試官問這個問題就是看看你對Service是否深入理解,Service不僅可以彈Toast還能彈出對話框,把Service看成Activity就行,所有的界面都是展示到Window窗體上面的,大家可以回顧下小衛士里面來點歸屬地不就是在服務里面進行監聽歸屬地進行展示的嗎。
答案解析:
可以的。彈吐司有個條件就是得有一個Context上下文,而Service本身就是Context的子類,因此在Service里面彈Toast是完全可以的。比如我們在Service中完成下載任務后可以彈一個Toast通知用戶。
你一般在什么情況下會使用Service?
經驗總結:
Service其實就是背地搞事情,又不想讓別人知道,舉一個生活當中的例子,陪女友去做胃鏡,管子才入口十五公分女友就惡心想吐,那么你就要擔心了,這婚后日子可咋過啊!看完這個,大家應該就理解了,你想知道一件事情不需要直接去問,你可以通過側面了解。這就是Service設計的初衷
Service為什么被設計出來?
根據Service的定義,我們可以知道需要長期在后臺進行的工作我們需要將其放在Service中去做。說得再通熟易懂一點,就是不能放在Activity中來執行的工作就必須得放到Service中去做。如:音樂播放、下載、上傳大文件、定時關閉應用等功能。這些功能如果放到Activity中做的話,那Activity退出被銷毀了的話,那這些功能也就停止了,這顯然是不符合我們的設計要求的,所以要將他們放在Service中去執行。
Activity怎么和service綁定,怎么在activity中啟動自己對應的service?
答案解析:
- Activity通過bindService(Intent service, ServiceConnection conn, int flags)跟Service進行綁定。
- 綁定成功以后,Service會將代理對象通過回調的形式傳遞給MyServiceConnection,這樣我們就獲取Service提供的代理對象
- 在Activity中可以通過startService和bindService方法啟動Service。
注意: 如果想獲取Service中提供的代理對象,那么必須通過bindService方法,進行綁定服務。
使用場景比如:音樂播放器,第三方支付等。
如果僅僅只是為了開啟一個后臺任務,那么可以使用startService方法。