Android概念篇(三)Service淺解

看完Activity後,再來當然是談Android的另外一個支柱:Service
Service被允許在背景中長時間執行,沒有UI介面
但可以持續跟App互動,進行IPC(Inter-ProcessCommunication)

Service生命週期
有兩種方式可以啟動Service
1. startService( ),2. bindService( )
兩者的生命週期圖如下:

startService( ) 從上圖可知,此方法啟動的service,是一條龍走到底
沒有任何callBack回來,做完就可以結束了
所以常用於download文件之類的一次性service
但是"如果未主動呼叫stopService( ),service便不會結束"
除非系統發現並回收掉

bindService( ) 可以被綁定於activity中,並能同時被多個綁定
綁定後可以用connection物件取得binder連結
透過此binder連結,便能調用service內的功能
粗略運作流程如下圖:

由於可以隨時被綁定並使用
適用於持續性的後端服務,同時可以有其他操作
使用情境例如背景音樂播放等功能。
但此被綁定的service,在綁定的activity結束時
會自動執行onUnBind(解除綁定)
直到沒有activity綁定此service時,service會自動finish( )掉

Service技巧
1.
上述的兩種方式都是"後端服務"
但不管下載文件、音樂撥放,
卻往往都能在通知欄看見一個bar?
這是使用了notification跳出通知在上頭
並以startForeground( )持續在前景顯示

2.
service是跑在mainThread中的,所以在service的生命週期中,
onCreate( )只會被執行一次,除非發生configChange(如螢幕旋轉)
而onStart()、stop()、onBind()、onUnBind()
則是可以被多次執行的

3.
承上一段,在mainThread中調用service時
如果等候回應太長時,超過五秒便會使App Crash
(即ANR, Application Not Responding)
所以通常會再new一個thread去bindService
利用非同步的機制,避免等候service回傳等到沒有回應
再以callBack的方式,得到執行結果

由於複雜耗時的執行放在service中,不易被系統回收
加上非同步執行緒,不占用mainThread
便能保證activity中的功能流暢執行,提高使用者體驗


4.
由於service有時會有被系統回收的可能
因此我們可以透過flag,來設定service的"生存模式"

START_STICKY
被殺死後會不斷重生

START_NOT_STICKY
被殺死後不會重生

START_REDELIVER_INTENT
被殺死後會不斷重生
並且殺死前會記錄狀態,重生後繼續進行

Service與Android 8
然而Android8.0之後,限制了背景service的持續時間
避免service看不到,卻佔用過多資源、又耗電
這時就需要改用JobScheduler(搭配JobInfo、JobService)
變成排時間表、週期性有規律地、特定情況下
才來執行service工作


小結
service可說是一個app的後勤部隊
而activity在前線作戰時,與後勤的溝通便相對重要
其中Handler、AsyncTask 觀念更是不可少
妥善使用service,免得app變成後台吃資源怪獸