Android面試Service篇

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。

今年年初我花一個月的時間收錄整理了一套知識體系,如果有想法深入的系統化的去學習的,可以私信我【安卓】,我會把我收錄整理的資料都送給大家,幫助大家更快的進階。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章