四大組件之Service

Service:

服務(Service) 是一種在後臺運行,沒有界面的組件,由其他組件調用開始。

service可以在和多場合的應用中使用,比如播放多媒體的時候用戶啓動了其他Activity這個時候程序要在後臺繼續播放,比如檢測SD卡上文件的變化,再或者在後臺記錄你地理信息位置的改變等等,總之服務嘛,總是藏在後頭的。

Service是在一段不定的時間運行在後臺,不和用戶交互應用組件。每個Service必須在manifest中 通過<service>來聲明。可以通過contect.startservice和contect.bindserverice來啓動。

Service和其他的應用組件一樣,運行在進程的主線程中。這就是說如果service需要很多耗時或者阻塞的操作,需要在其子線程中實現。


service的兩種模式(startService()/bindService()不是完全分離的):

本地服務 Local Service 用於應用程序內部。


它可以啓動並運行,直至有人停止了它或它自己停止。在這種方式下,它以調用Context.startService()啓動,而以調用Context.stopService()結束。它可以調用Service.stopSelf() 或 Service.stopSelfResult()來自己停止。不論調用了多少次startService()方法,你只需要調用一次stopService()來停止服務。

用於實現應用程序自己的一些耗時任務,比如查詢升級信息,並不佔用應用程序比如Activity所屬線程,而是單開線程後臺執行,這樣用戶體驗比較好。
遠程服務 Remote Service 用於android系統內部的應用程序之間。


它可以通過自己定義並暴露出來的接口進行程序操作。客戶端建立一個到服務對象的連接,並通過那個連接來調用服務。連接以調用Context.bindService()方法建立,以調用 Context.unbindService()關閉。多個客戶端可以綁定至同一個服務。如果服務此時還沒有加載,bindService()會先加載它。


可被其他應用程序複用,比如天氣預報服務,其他應用程序不需要再寫這樣的服務,調用已有的即可。

生命週期:




1.使用context.startService() 啓動Service是會會經歷:

  context.startService() ->onCreate()- >onStart()->Service running

  context.stopService() | ->onDestroy() ->Service stop

  如果Service還沒有運行,則android先調用onCreate()然後調用onStart();如果Service已經運行,則只調用onStart(),所以一個Service的onStart方法可能會重複調用多次。

  stopService的時候直接onDestroy,如果是調用者自己直接退出而沒有調用stopService的話,Service會一直在後臺運行。該Service的調用者再啓動起來後可以通過stopService關閉Service。

  所以調用startService的生命週期爲:onCreate --> onStart(可多次調用) --> onDestroy


        2.使用使用context.bindService()啓動Service會經歷:

  context.bindService()->onCreate()->onBind()->Service running

  onUnbind() -> onDestroy() ->Service stop

  onBind將返回給客戶端一個IBind接口實例,IBind允許客戶端回調服務的方法,比如得到Service運行的狀態或其他操作。這個時候把調用者(Context,例如Activity)會和Service綁定在一起,Context退出了,Srevice就會調用onUnbind->onDestroy相應退出。

  所以調用bindService的生命週期爲:onCreate --> onBind(只一次,不可多次綁定) --> onUnbind --> onDestory。


  在Service每一次的開啓關閉過程中,只有onStart可被多次調用(通過多次startService調用),其他onCreate,onBind,onUnbind,onDestory在一個生命週期中只能被調用一次。


啓動Service


根據onStartCommand的返回值不同,有兩個附加的模式:


  1. START_STICKY 用於顯示啓動和停止service。

  2. START_NOT_STICKY或START_REDELIVER_INTENT用於有命令需要處理時才運行的模式。

  服務不能自己運行,需要通過調用Context.startService()或Context.bindService()方法啓動服務。這兩個方法都可以啓動Service,但是它們的使用場合有所不同。

  1. 使用startService()方法啓用服務,調用者與服務之間沒有關連,即使調用者退出了,服務仍然運行。

  如果打算採用Context.startService()方法啓動服務,在服務未被創建時,系統會先調用服務的onCreate()方法,接着調用onStart()方法。

  如果調用startService()方法前服務已經被創建,多次調用startService()方法並不會導致多次創建服務,但會導致多次調用onStart()方法。

  採用startService()方法啓動的服務,只能調用Context.stopService()方法結束服務,服務結束時會調用onDestroy()方法。

  2. 使用bindService()方法啓用服務,調用者與服務綁定在了一起,調用者一旦退出,服務也就終止,大有“不求同時生,必須同時死”的特點。

  onBind()只有採用Context.bindService()方法啓動服務時纔會回調該方法。該方法在調用者與服務綁定時被調用,當調用者與服務已經綁定,多次調用Context.bindService()方法並不會導致該方法被多次調用。

  採用Context.bindService()方法啓動服務時只能調用onUnbind()方法解除調用者與服務解除,服務結束時會調用onDestroy()方法。


官方文檔:

一個service可以同時start並且bind,在這樣的情況,系統會一直保持service的運行狀態如果service已經start了或者BIND_AUTO_CREATE標誌被設置。如果沒有一個條件滿足,那麼系統將會調用onDestory方法來終止service.所有的清理工作(終止線程,反註冊接收器)都在onDestory中完成。

  擁有service的進程具有較高的優先級

  Android系統會盡量保持擁有service的進程運行,只要在該service已經被啓動(start)或者客戶端連接(bindService)到它。當內存不足時,需要保持,擁有service的進程具有較高的優先級。

  1. 如果service正在調用onCreate,onStartCommand或者onDestory方法,那麼用於當前service的進程則變爲前臺進程以避免被killed。

  2. 如果當前service已經被啓動(start),擁有它的進程則比那些用戶可見的進程優先級低一些,但是比那些不可見的進程更重要,這就意味着service一般不會被killed.

  3. 如果客戶端已經連接到service (bindService),那麼擁有Service的進程則擁有最高的優先級,可以認爲service是可見的。

  4. 如果service可以使用startForeground(int, Notification)方法來將service設置爲前臺狀態,那麼系統就認爲是對用戶可見的,並不會在內存不足時killed。

  如果有其他的應用組件作爲Service,Activity等運行在相同的進程中,那麼將會增加該進程的重要性。





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