一個Service是沒有介面且能長時間運行於背景應用組件.其它應用的組件可以啟動一個服務運行於後台,即使使用者切換到另一個應用也會繼續運行.另外,一個組件可以綁定到一個service來進行互動,即使這個互動是進程間通訊也沒問題.例如,一個aservice可能處理網路事物,播放音樂,執行檔案I/O,或與一個內容提供者互動,所有這些都在後台進行.
一個service本質上可有兩種表現形式:
Started
一個service在某個應用組件(比如一個activity)調用startService()時就處於"started"狀態(注意,可能已經啟動了).一旦運行後,service可以在後台無限期地運行,即使啟動它的組件銷毀了.通常地,一個startedservice執行一個單一的操作並且不會返回給調用者結果.例如,它可能通過網路下載或上傳一個檔案.當操作完成後,service自己就停止了
Bound
一個service在某個應用組件調用bindService()時就處於"bound"狀態.一個boundservice提供一個client-server介面以使組件可以與service互動,發送請求,擷取結果,甚至通過進程間通訊進行交叉進行這些互動.一個boundservice僅在有其它應用的組件綁定它時運行.多個應用組件可以同時綁定到一個service,但是當所有的自由競爭組件不再綁定時,service就銷毀了.
儘管這個文檔是把這兩種service分開講的,但你的service可以在這兩種方式下工作.—它可以是started(無限期運行)同時也允許綁定.唯一的簡單問題是你是否實現了一對回調方法:onStartCommand()允許組件啟動它並且onBind()允許綁定.
不論你是應用是否啟動,或綁定到一個服務或兩者都做了,任何應用組件都可以使用service(即使從另一個應用),跟任何組件都可以使用activity一樣—通過一個Intent啟動它.然而,你可以在manifest檔案中聲明服務為私人,並且阻止另外的應用訪問它.這在講如何於manifest檔案中聲明service時會詳細講解.
注意:一個service是運行在它所在進程的主線程中的—service不會建立它自己的thread也不會運行於單獨的進程(除非你另外指定).這表示,如果你的service想做一些狂耗CPU的工作或阻塞型的操作(比如MP3播放或網路通訊),你必須在service中建立一個新的線程來做那些工作.通過使用一個分離的線程,你將減少"應用沒有反應"(ANR)錯誤並且應用的主線程可以保持activity對使用者操作的快速反應.
基礎
你應使用一個service還是線程?
一個service是一個在使用者不與你的應用互動時依然可以運行於背景簡單組件.所以,只有你需要這樣做時才建立一個service.
如果你需要執行的工作不在主線程中,但是只有使用者在與你的應用互動時才進行,那麼你可能應該建立一個新的線程而不是一個service.例如,如果你想播放一些音樂,但是只在你的activity運行時才播放,你應該在onCreate()中建立一個線程,在onStart()運行這個線程,然後在onStop()中停止它.也可以考慮使用AsyncTask或HandlerThread,來代替傳統的線程類.
記住,如果你使用了service,它預設會固定運行於你的應用的主線程,所以你應該在其中建立一個線程來執行耗時或阻塞的操作.
要建立一個service,你必須建立一個Service類(或某個已存在的子類)的子類.在你的實現中,你應覆寫一些處理有關service生命期的關鍵方面的回調方法並且提供一個能讓組件綁定到service的機制(如果需要).你應覆寫的最重要的回調方法是:
onStartCommand()
系統在其它組件比如activity通過調用startService()請求service啟動時調用這個方法.一旦這個方法執行,service就啟動並且在後台長期運行.如果你實現了它,你需要負責在service完成任務時停止它,通過調用stopSelf()或stopService().(如果你只想提供綁定,你不需實現此方法).
OnBind()
當組件調用bindService()想要綁定到service時(比如想要執行進程間通訊)系統調用此方法.在你的實現中,你必須提供一個返回一個IBinder來以使用戶端能夠使用它與service通訊,你必須總是實現這個方法,但是如果你不允許綁定,那麼你應返回null.
OnCreate()
系統在service第一次建立時執行此方法,來執行只運行一次的初始化工作(在調用它方法如onStartCommand()或onBind()之前).如果service已經運行,這個方法不會被調用.
OnDestroy()
系統在service不再被使用並要銷毀時調用此方法.你的service應在此方法中釋放資源,比如線程,登入的接聽程式,接收器等等.這是service收到的最後一個調用.
如果一個組件通過調用startService()啟動一個service(最終導致onStartCommand()被調用),之後service會保持運行,直到它通過stopSelf()停止自己或另外的組件調用stopService()停止它.
如果一個組件調用bindService()來建立service(onStartCommand()不會被調用),那麼service只是運行在綁定期間.一旦service從所有的用戶端解除綁定,系統就會殺了它.
Android系統只在記憶體很少並且必須為具有使用者焦點的actvity釋放資源時才會強制停止一個service.如果service是綁定到具有使用者焦點的activity上,那麼它很難被殺死,並且如果service被聲明為運行於前台(後面將討論),那麼它將永不被殺死,除非,如果這個service啟動並且長期運行,那麼系統將會降低它在背景工作逾時列表中的位置然後這個將變成高度易被殺對象—如果你的service被啟動,那麼它必須被設計為能優雅地處理被系統重啟的操作.如果系統殺死了你的service,它會在資源重新可用時立馬重啟它(但是依賴於你在onStartCommand()中的傳回值).關於系統何時殺死一個service的更多資訊,請看:android
進程與線程詳解.