Android系統編程入門系列之加載服務Service

以前幾篇文章簡單梳理了在Android系統的四大組件之一,最主要的界面Activity中,使應用程序與用戶進行交互響應的相關知識點,那對於應用程序中不須要與用戶交互的邏輯,又要用到哪些內容呢?本文開始將介紹應用程序無需界面交互的內部交互相關知識點,首先從另一個四大組件之一的服務Service開始。html

清單文件一文的組件聲明中,已經知道服務Service與界面Activity同樣,都要在清單文件中註冊聲明。一樣的,每一個註冊聲明的服務Service類向上追溯都必須繼承自android.app.Service父類,所以服務Service也有本身的生命週期。android

生命週期

Service主要負責應用程序中不須要界面展現或交互的長時間操做,像是播放音樂,網絡請求等都是能夠在服務Service中完成的。與界面Activity的生命週期同樣,在服務Service的聲明週期內不容許執行耗時操做,因此,雖然服務Service中能夠進行長時間操做,可是仍然須要將這部分耗時操做放入非Android系統主線程中。網絡

(調用構造方法)對象實例化

首次啓動新的服務Service時,系統會申請內存空間存儲該服務Service的實例化對象。服務Service兩種啓動方式,其一與界面Activity同樣須要藉助意圖Intent對象,調用上下文環境Context對象的startService(Intent service)啓動。app

其二是進程間通訊時所用的方式,不只要藉助意圖Intent對象,還要使用實現android.content.ServiceConnection接口的對象,進而調用上下文環境Context對象的bindService(Intent service, ServiceConnection conn, int flags)方法,而參數三 flags 標記了啓動該服務Service時所綁定的模式,一般使用Context.BIND_AUTO_CREATE標記會自動建立當前綁定的服務Service。除此以外,還能夠按位或的形式追加其餘標記,例如追加|Context.BIND_NOT_FOREGROUND標記當前綁定服務Service爲較低優先級的後臺服務,在手機息屏或高能耗時,系統會優先殺死低優先級的服務;而追加|Context.BIND_IMPORTANT標記能夠提高綁定服務Service的優先級爲前臺服務,在手機息屏或高能耗時,只要當前應用程序存活,當前服務Service就不會被殺死;若是追加|Context.BIND_ABOVE_CLIENT標記當前綁定服務Service的優先級要高於當前應用程序,當手機息屏或高能耗時,系統可能會先殺死應用程序,可是當前服務Service仍然存活。google

Android系統爲不一樣進程間的通訊提供了一套AIDL語言規範,詳情將在之後的文章中介紹,這裏只需瞭解在實現ServiceConnection接口中,要重寫兩個方法,分別是在進程通訊接口與服務Service鏈接成功後回調的onServiceConnected(ComponentName name, IBinder service)方法,和鏈接斷開以後回調的onServiceDisconnected(ComponentName name)方法。線程

上述兩種啓動方式,都會觸發系統在當前應用程序的清單文件中查找對應註冊過的服務Service,在找到以後,就會建立其實例化對象,若是在清單文件中沒有找到對應的服務Service,將不會有任何錯誤或異常。設計

與啓動未註冊的服務Service不一樣的是,當調用startActivity()系列方法啓動一個沒有在清單文件中註冊過的界面Activity時,系統一般會拋出android.content.ActivityNotFoundException異常。code

(調用attachBaseContext(Context base))加載運行環境

因爲Service也是android.content.ContentWrapper的子類,因此係統在建立服務Service的實例化對象後,也會優先對其加載上下文運行環境,將參數 base 做爲當前應用程序的Context對象與該服務Service綁定。在該方法被調用以後的任意位置,就能夠經過調用getBaseContext()等系列方法獲取並使用當前服務Service所在的上下文環境了。htm

(調用onCreate())服務建立

在建立服務Service並加載運行環境以後,系統會優先調用該方法,表示當前服務已經完成建立。能夠重寫該方法執行一些服務內部使用的資源初始化操做。在執行完該方法以後,就標誌着當前服務Service建立成功了,以後會一直處於運行狀態,同時根據上述啓動方式的不一樣,調用不一樣的生命週期方法。對象

(調用onStartCommand(Intent intent, int flags, int startId))服務啓動

若是是經過上述啓動方式一啓動的服務Service,每調用一次startService(),系統都會調用一次該方法。
其中參數 intent 接收每次啓動服務所傳入的Intent意圖。
參數 flags 標記當前服務屢次啓動狀態,通常默認是 0 ;當該服務Service被首次調用該方法且成功返回Service.START_REDELIVER_INTENT=3後,莫名被系統殺死,以後再次啓動該服務時,標記參數則是 Service.START_FLAG_REDELIVERY=1 ;若是該服務Service被首次調用該方法並未返回結果,系統將會再次嘗試調用該方法,標記參數則爲 Service.START_FLAG_RETRY=2
參數 startId 做爲系統惟一值,以此標記當前服務Service
最終返回指定的int類型,若是返回默認的Service.START_STICKY_COMPATIBILITY=0,當系統殺死該服務Service後,再次調用startService()將不會再被系統回調該方法;另外若是返回Service.START_STICKY=1,在系統殺死該服務Service後,再次調用startService()將會被系統從新建立實例化並回調該方法。

(調用onBind(Intent intent))服務綁定

若是是經過上述啓動方式二啓動的服務Service,在首次調用bindService()後,系統會調用該方法,而以後若是屢次調用bindService(),只有在當前服務Service已經執行完onUnbind()解綁的生命週期方法,並在解綁方法中返回 false 時,系統纔會回調該方法。參數 intent 接收綁定服務所傳入的Intent意圖,最終返回android.os.IBinder接口的實現類對象。返回結果能夠在bindService(Intent service, ServiceConnection conn, int flags)方法的參數二conn.onServiceConnected(ComponentName name, IBinder service)方法中接收,也就是其中的參數二IBinder類型的 service

服務解綁(調用onUnbind(Intent intent))

若是是經過上述啓動方式二啓動的服務Service,能夠在bindService()綁定服務Service位置相對應的位置,調用unbindService()解綁服務Service。以後系統會回調該方法,一樣的藉助參數Intent意圖實例來指定要解綁的指令信息。

服務重綁(調用onRebind(Intent intent))

若是是經過上述啓動方式二啓動的服務Service,若是當前服務Service已經執行完解綁生命週期,並在onUnbind()方法中返回 true 時,系統將會調用該方法以使用原有的IBinder對象從新綁定當前服務Service,所以該方法不須要返回值。其參數 intent 接收綁定服務所傳入的Intent意圖。最終返回值boolean類型,以標記當前服務再次被綁定時是否使用原有綁定過的IBinder對象。

服務銷燬(調用onDestroy())

啓動以後的服務Service會一直處於運行狀態,直到系統可能因能耗過過而殺死低優先級的進程時,當前服務Service將會被動殺死,或者當前服務Service主動調用代碼中止運行。與上述兩種啓動方式對應,服務Service也有兩種中止方式
其一對應於startService()啓動的服務,調用上下文環境Context對象的stopService(Intent service)方法中止運行,或者調用當前服務Service對象的stopSelf()方法也能夠中止運行自身服務。
其二對應於bindService()綁定的服務,調用上下文環境Context對象的unbindService(ServiceConnection conn)方法解除綁定。因爲綁定該服務的能夠有多個ServiceCOnnection鏈接,因此必須每一個bindService()綁定服務的位置都對應調用unbindService()方法主動解綁,以防止出現內存泄漏或資源佔用等誤操做。

在服務Service全部綁定已解綁或主動中止運行後,系統最終會調用該方法,以後將銷燬內存中建立的該服務Service實例化對象。所以能夠重寫該方法,對應於onCreate()中申請的初始化資源在該方法中釋放掉。


服務Service的生命週期與界面Activity有些相似,這也保證了在其中能夠執行無用戶交互的操做,那麼針對這種應用場景還須要怎麼構建子線程操做呢?並且服務Service的設計還能夠進行進程間通訊。具體又是如何編寫代碼搭建進程間的溝通橋樑呢?敬請期待後續文章。

相關文章
相關標籤/搜索