Android ServiceConnection


綁定到一個Service

應用組件(客戶端)可以調用bindService()綁定到一個service.Android系統之后調用service的onBind()方法,它返回一個用來與service交互的IBinder.

綁定是異步的.bindService()會立即返回,它不會返回IBinder給客戶端.要接收IBinder,客戶端必須創建一個ServiceConnection的實例並傳給bindService().ServiceConnection包含一個回調方法,系統調用這個方法來傳遞要返回的IBinder.

 

注:只有activities,services,和contentproviders可以綁定到一個service—你不能從一個broadcastreceiver綁定到service.

所以,從你的客戶端綁定到一個service,你必須:

  • 1實現ServiceConnection.

    你的實現必須重寫兩個回調方法:

    • onServiceConnected()

      系統調用這個來傳送在service的onBind()中返回的IBinder.

    • OnServiceDisconnected()

      Android系統在同service的連接意外丟失時調用這個.比如當service崩潰了或被強殺了.當客戶端解除綁定時,這個方法不會被調用.

  • 2調用bindService(),傳給它ServiceConnection的實現.

  • 3當系統調用你的onServiceConnected()方法時,你就可以使用接口定義的方法們開始調用service了.

  • 4要與service斷開連接,調用unbindService().

      當你的客戶端被銷毀,它將從service解除綁定,但是你必須總是在你完成與service的交互時或當你的activity暫停於是service在不被使用時可以關閉此兩種情況下解除綁定.(下面會討論更多在適當的時候綁定和解除綁定的問題.)

例如,下面是前一篇"派生Binder類"中創建的代碼片段,它把客戶端連接到了service.所有需要做的就是把返回的IBinder強制轉換到LocalBinder類並且請求LocalService實例:

 

LocalService mService;  
private ServiceConnection mConnection = new ServiceConnection() {  
    // 當與service的連接建立后被調用  
    public void onServiceConnected(ComponentName className, IBinder service) {  
        // Because we have bound to an explicit  
        // service that is running in our own process, we can  
        // cast its IBinder to a concrete class and directly access it.  
        LocalBinder binder = (LocalBinder) service;  
        mService = binder.getService();  
        mBound = true;  
    }  
  
    // 當與service的連接意外斷開時被調用  
    public void onServiceDisconnected(ComponentName className) {  
        Log.e(TAG, "onServiceDisconnected");  
        mBound = false;  
    }  
};  

使用這個ServiceConnection,客戶端可以綁定到一個service,通過把它傳給bindService().例如:

Intentintent = new Intent(this, LocalService.class);

bindService(intent,mConnection, Context.BIND_AUTO_CREATE);

  • 第一個bindService()的參數是一個明確指定了要綁定的service的Intent.

  • 第二個參數是ServiceConnection對象.

  • 第三個參數是一個標志,它表明綁定中的操作.它一般應是BIND_AUTO_CREATE,這樣就會在service不存在時創建一個.其它可選的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,不想指定時設為0即可.

補充事項

下面是一些關於綁定到service的重要事項:

  • 你總是需要捕獲DeadObjectException異常.它會在連接被打斷時拋出.這是被遠程方法拋出的唯一異常.

  • 對象引用計數是跨進程的作用的.

  • 你應該在客戶端的生命期內使綁定和解除綁定配對進行,例如:

    • 如果你需要在你的activity可見時與service交互,你應該在onStart()綁定並在onStop()中解除綁定.

    • 如果你想讓你的activity即使在它停止時也能接收回應,那么你可以在onCreate()中綁定並在onDestroy()中解除綁定.注意這意味着你的activity需要使用在自己整個運行期間使用service(即使位於后台),所以如果service在另一個進程中,那么你增加了這個進程的負擔而使它變得更容易被系統殺掉.

  注:你一般不應該在你的activity的onResume()和onPause()中綁定和解除綁定到service,因為這些回調方法,出現在每個生命期變化中,並且你需要使發生在這些變化中的處理最小化.還有,如果你應用中的多個activity綁定到同一個service,並且有一個變化發生在其中兩個activity之間,service可能在當前activity解除綁定(pause中)和下一個綁定前(rusume中)被銷毀又重建.

管理BoundService的生命期

  當一個service的所有客戶端都解除綁定,Android系統就銷毀它(除非它是從onStartCommand()啟動).如果你的service是一個純boundservice,你不需管理它的生命期—Android系統會為你管理它.

  然而,如果你選擇了實現onStartCommand()回調方法,那么你必須明確地停止service,因為service現在被認為是"開始的".在此情況下,service會一直運行,直到service使用stopSelf()停止它自己或另外的組件調用了stopService()停止了它,不管是否有客戶端綁定了它.

  另外,如果你的service已經啟動並且接受綁定,那么當系統調用你的onUnbind()方法,你可以選擇返回true表示你想在客戶端下一次綁定到service時接受一個對onRebind()的調用(而不是一個對onBind()的調用)onRebind()返回void,但是客戶端依然會在它的onServiceConnected()回調中接收到IBinder.下圖演示了這種生命其的邏輯:


 

圖1.一個已開始並已綁定的service的生命期


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM