Service是面試中經常問到的一個模塊,從之前的簡單使用,到後期的應用保活,當然現在Android系統對這種保活機制進行了優化和限制,我們先簡單瞭解下Service的特性。
接下來的文章主要以一問一答的方式進行介紹Service的特性,必要部分也會分析到Service的源碼邏輯
首先啥是Service?
- 雖然大家都知道啥是Service,但是我也得甩個定義。
- Service是Android系統中的四大組件之一,主要有兩個應用場景:後臺運行和跨進程訪問。Service可以在後臺執行長時間運行操作而不提供用戶界面,除非系統必須回收內存資源,否則系統不會停止或銷燬服務。服務可由其他應用組件啓動,而且即使用戶切換到其他應用,服務仍將在後臺繼續運行。 此外,組件可以綁定到服務,以與之進行交互,甚至是執行進程間通信 (IPC)。
Service啓動方式有幾種?
- 啓動方式有兩種。
- startService(Intent)
- bindService(Intent,ServiceConnection,flags);
startService和bindService啓動服務有什麼區別?
- 這兩種啓動方式的生命週期不同。
startService:onCreate()-onStartCommand()-onDestroy();
bindService:onCreate()-onBind()-onServiceConnected()-onUnBind()-onDestroy();
混合調用,先startService後bindService
onCreate()-onStartCommand()-onBind()-onServiceConnected()-onUnBind()-onDestroy()
混合調用,先bindService後startService
onCreate()-onBind()-onServiceConnected()-onStartCommand()-onUnBind()-onDestroy()
- 啓動者結束後,使用startService啓動的Service會繼續執行,因爲startService是獨立進程,使用bindService啓動的服務會立即結束並拋異常提醒。
- startService獨立進程 資源佔用也會比較多。
多次調用startService或者bindService會重複執行生命週期麼?
- 重複startService會重複執行onStartCommand(),但onCreate()只會執行一次。
- 重複bindService所有Service的生命週期都不重複執行,onCreate(),onBind()只執行一次。
- 補充:通過tartService和bindService混合啓動的Service至少點擊一次stopService和unbindService。
Service 怎麼和Activity進行通信?
- 可通過Binder對象進行通信。
- 可通過BroadCast Receiver
- 通過Handler藉助Binder
- 通過回調藉助Binder
爲什麼bindService可以跟Activity生命週期聯動?
- 這個問題字面是在考察Service的聯動現象,實在考察對Android源碼的理解,接下來咱們就針對源碼捋一遍。
首先我們知道,bindService 方法執行時,會回調到onServiceConnected()。
- 那onServiceConnected是怎麼回調的?又是由誰回調的?
Service的大部分操作均由ActivityThread的內部類H處理。
- onServiceConnected()調用鏈如下所示:
H->handleMessage()
handleBindService()
IBinder binder = mServices.get(data.token).onBind();
// ActivityManager.getService()得到的是一個ActivityManagerService對象。
ActivityManager.getService().publishService(,, binder);
//ActivityManagerService對象是在系統進程中,所以當前線程會掛起,啓用系統進程調用publishServiceLocked()
ActiveServices.publishServiceLocked(,, binder);
//c.conn.connected又從系統的服務進程回到了應用進程,connected方法就是LoadApk的內部類InnerConnection.connected()方法.
c.conn.connected(r.name, binder, false);
LoadedApk.ServiceDispatcher.connected(, binder, );
LoadedApk.ServiceDispatcher.doConnected(, binder, );
ServiceConnection.onServiceDisconnected();
ServiceConnection.onServiceConnected();
- 以上執行過程中LoadedApk會記錄 ServiceConnection 信息。
當Activity 執行 finish 方法時,會通過 LoadedApk檢查Activity是否存在未註銷/解綁的 BroadcastReceiver 和 ServiceConnection。
如果有未解綁的對象,則通知 AMS 註銷/解綁對應的 BroadcastReceiver 和 Service,並打印異常信息,告訴用戶應該主動執行註銷/解綁的操作。
注:
- Service的所有生命週期方法和ServiceConnection的回調方法都是運行在主線程的。所以在開發中特別要注意,千萬不能在Service的生命週期方法中做非常耗時的操作,否則會引起主線程卡頓,嚴重時還會引起ANR。
今年年初我花一個月的時間收錄整理了一套知識體系,如果有想法深入的系統化的去學習的,可以私信我【安卓】,我會把我收錄整理的資料都送給大家,幫助大家更快的進階。