一.什麼是Service Service是一個應用程式組件,它是安卓實現程式後臺運行的一個解決方案。 二.分類 服務有兩種類別started、bound.但是一個服務類所要繼承的類是一樣的,都是Service類。也就是說,一個服務,可以包含上面兩種運行方式的服務,只是與它重載的方法有關,如果重寫了o ...
一.什麼是Service
Service是一個應用程式組件,它是安卓實現程式後臺運行的一個解決方案。
二.分類
服務有兩種類別started、bound.但是一個服務類所要繼承的類是一樣的,都是Service類。也就是說,一個服務,可以包含上面兩種運行方式的服務,只是與它重載的方法有關,如果重寫了onStartCommand()即支持啟動服務,如果重寫onBiind()即支持綁定服務,所以如果同時重載實現這兩個方法即可實現兩種服務。
1.Started
如果一個應用程式組件(比如一個activity)通過調用startService()來啟動服務,則該服務就是被“started”了。一旦被啟動,服務就能在後臺一直運行下去,即使啟動它的組件已經被銷毀了。 通常,started的服務執行單一的操作並且不會向調用者返回結果。比如,它可以通過網路下載或上傳文件。當操作完成後,服務應該自行終止。
2.Bound
如果一個應用程式組件通過調用bindService()綁定到服務上,則該服務就是被“bound”了。bound服務提供了一個客戶端/伺服器介面,允許組件與服務進行交互、發送請求、獲取結果,甚至可以利用進程間通信(IPC)跨進程執行這些操作。綁定服務的生存期和被綁定的應用程式組件一致。 多個組件可以同時與一個服務綁定,不過所有的組件解除綁定後,服務也就會被銷毀。
服務生命周期
根據前面的描述也可以知道,兩種服務的生命周期是不一樣的
三.幾個主要方法
1.OnStartCommand()
當其它組件,比如一個activity,通過調用startService()請求started方式的服務時,系統將會調用本方法。 一旦本方法執行,服務就被啟動,併在後臺一直運行下去。 如果你的代碼實現了本方法,你就有責任在完成工作後通過調用stopSelf()或stopService()終止服務。 (如果你只想提供bind方式,那就不需要實現本方法。)請註意onStartCommand()方法必須返回一個整數。這個整數是描述系統在殺死服務之後應該如何繼續運行(IntentService 實現代碼會替你處理這一點,當然那樣你就無法修改這個處理過程)。onStartCommand()的返回值必須是以下常量之一:STARTNOTSTICKY,STARTSTICKY,STARTREDELIVER_INTENT
2.OnBlind
當其它組件需要通過bindService()綁定服務時,系統會調用本方法。客戶端用它來和服務進行通信。 你必須確保實現本方法,不過假如你不需要提供綁定,那就返回null即可。
3.OnCreate()
4.OnDestory
5.終止服務
一個started服務必須自行管理生命周期。也就是說,系統不會終止或銷毀這類服務,除非必須恢復系統記憶體並且服務返回後一直維持運行。 因此,服務必須通過調用stopSelf()自行終止,或者其它組件可通過調用stopService()來終止它
四.IntentService
除了繼承Service,也可以繼承IntentService。因為大多數started服務都不需要同時處理多個請求(這實際上是一個危險的多線程情況),所以最佳方式也許就是用IntentService類來實現你的服務。註意:構造方法是必需的,必須用工作線程名稱作為參數。
使用情景:
我們或許會碰到這麼一種業務需求,一項任務分成幾個子任務,子任務按順序先後執行,子任務全部執行完後,這項任務才算成功。那麼,利用幾個子線程順序執行是可以達到這個目的的,但是每個線程必須去手動控制,而且得在一個子線程執行完後,再開啟另一個子線程。或者,全部放到一個線程中讓其順序執行。這樣都可以做到,但是,如果這是一個後臺任務,就得放到Service裡面,由於Service和Activity是同級的,所以,要執行耗時任務,就得在Service裡面開子線程來執行。那麼,有沒有一種簡單的方法來處理這個過程呢,答案就是IntentService。(具體可見:http://www.cnblogs.com/yydcdut/p/3960886.html)
五.相對於後臺,還有前臺服務
前臺服務是指那些經常會被用戶關註的服務,因此記憶體過低時它不會成為被殺的對象。 前臺服務必須提供一個狀態欄通知,並會置於“正在進行的”(“Ongoing”)組之下。這意味著只有在服務被終止或從前臺移除之後,此通知才能被解除。 要把你的服務請求為前臺運行,可以調用startForeground()方法。此方法有兩個參數:唯一標識通知的整數值、狀態欄通知Notification對象。
public class MyFrontService(){ ... @override public void onCreate(){ super.onCreate(); Notification notification = new Notification(R.drawable.icon,"通知來了"),System.currentTimeMillis()); Intent notificationIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); //其中的參數id是一個唯一標識通知的整數,但是這裡註意這個整數一定不能為0 notification.setLatestEventInfo(this, "標題", “內容”, pendingIntent); startForeground(ONGOING_NOTIFICATION, notification); } }
六.使用場景:服務還是線程
服務僅僅是一個組件,即使用戶不再與你的應用程式發生交互,它仍然能在後臺運行。因此,應該只在需要時才創建一個服務。
如果你需要在主線程之外執行一些工作,但僅當用戶與你的應用程式交互時才會用到,那你應該創建一個新的線程而不是創建服務。 比如,如果你需要播放一些音樂,但只是當你的activity在運行時才需要播放,你可以在onCreate()中創建一個線程,在onStart()中開始運行,然後在onStop()中終止運行。還可以考慮使用AsyncTask或HandlerThread來取代傳統的Thread類。關於線程的詳細信息,請參閱進程和線程。
請記住,如果你使用了服務,它預設就運行於應用程式的主線程中。因此,如果服務執行密集計算或者阻塞操作,你仍然應該在服務中創建一個新的線程來完成。
最後推薦一個很酷的線上作圖網站:https://www.processon.com/tour