close

之前提及過,啟動Service有兩種方式:startService 與 bindService。前者已經說過如何使用,所以,這篇貼子主要是關於 bind service的。 這裡所討論的是僅針對那些被綁定的service的,而那些既被startService() 又被 bindService() 的 service 不在此範圍內。

1 Bind Service就像是C/S架構中的服務端,其他組件(比如 Activity)綁定到它(通過 bindService()),可以向它發送請求,可以接受從它返回的響應,它甚至還提供了進程間通信(IPC)功能。

2 一個service要想能夠被其他組件綁定,那麼它的 onBind() 方法必須被實現,且必須返回一個 IBinder 對象,然後其他組件可以通過這個 IBinder 對象與該 service 進行通訊。

3 多個client可以綁定至同一個service,但該 service 的onBind() 方法只會在第一個 client 綁定至其的時候被調用,當其他 client 再次綁定到它的時候,並不會調用  onBind() 方法,而是直接返回第一次被調用時產生的那個 IBinder 對象。也就是說,在其生命週期內,onBind() 只會被調用一次。

4 Bind Service 的生命週期如下圖所示:



 

5 Bind Service 不會在後台無限期的一直運行,而是當所有綁定至其的組件都調用了 unbindService() 進行解綁之後,系統就會將其停掉以回收資源。

 

6 當我們要實現一個 Bind Service 的時候,最重要的就是實現它的 onBind() 方法以返回一個 IBinder 對像

 

要生成一個 Bound Service ,共有三種方式:繼承自 Binder 類,使用 Messenger ,使用 AIDL。下面且聽小生一一道來。

第一種:繼承自 Binder 類

需要注意的是,這種方式僅僅適用於這種場合:service 與 application 在同一個進程中。這種場合也是最最常見的。

它分以下幾個步驟:

a. 在你的 service 類中聲明一個內部類來繼承 Binder 類。在該內部類中,最好提供一個公共方法來返回你的 service 實例。

b. 在你的 service 類中需要聲明一個這個內部類的實例,以供在 onBind() 方法中返回

c. 在 client 端,在 onServiceConnected() 方法中得到從 onBind() 方法中返回的 IBinder 對象,然後可以通過該 對像中的公共方法得到相應的 service 實例,正如 第一個步驟 所說的那樣。

d. 在 service 中提供公共方法, 這樣就可以在組件(如 Activity 中調用這些公共方法了)

 

下面給出一例:

service 代碼

Java代碼  收藏代码
  1. public class BindServiceWithIBinder extends Service {  
  2.   
  3.     private static final String TAG = "BindServiceWithIBinder";  
  4.   
  5.     private final MyIBinder myIBinder = new MyIBinder();  
  6.   
  7.     /** 
  8.      * bindService() 時,調用的是這個方法,而非 onStartCommnad() 方法 
  9.      */  
  10.     @Override  
  11.     public IBinder onBind(Intent intent) {  
  12.         // 在主 Activity 上的 TextView 中打印出一行LOG  
  13.         MyServiceActivity.vh.sendMessage(MyServiceActivity.createMessage(  
  14.                 MyServiceActivity.UPDATE_VIEW, TAG + " ----> onBind"));  
  15.         return myIBinder;  
  16.     }  
  17.   
  18.     @Override  
  19.     public void onCreate() {  
  20.         MyServiceActivity.vh.sendMessage(MyServiceActivity.createMessage(  
  21.                 MyServiceActivity.UPDATE_VIEW, TAG + " ----> onCreate"));  
  22.     }  
  23.   
  24.     @Override  
  25.     public void onDestroy() {  
  26.         MyServiceActivity.vh.sendMessage(MyServiceActivity.createMessage(  
  27.                 MyServiceActivity.UPDATE_VIEW, TAG + " ----> onDestroy"));  
  28.     }  
  29.   
  30.     @Override  
  31.     public void onRebind(Intent intent) {  
  32.         MyServiceActivity.vh.sendMessage(MyServiceActivity.createMessage(  
  33.                 MyServiceActivity.UPDATE_VIEW, TAG + " ----> onRebind"));  
  34.     }  
  35.   
  36.     @Override  
  37.     public int onStartCommand(Intent intent, int flags, int startId) {  
  38.         MyServiceActivity.vh.sendMessage(MyServiceActivity.createMessage(  
  39.                 MyServiceActivity.UPDATE_VIEW, TAG + " ----> onStartCommand"));  
  40.         return START_STICKY;  
  41.     }  
  42.   
  43.     @Override  
  44.     public boolean onUnbind(Intent intent) {  
  45.         MyServiceActivity.vh.sendMessage(MyServiceActivity.createMessage(  
  46.                 MyServiceActivity.UPDATE_VIEW, TAG + " ----> onUnbind"));  
  47.         return super.onUnbind(intent);  
  48.     }  
  49.   
  50.     /** 
  51.      * 聲明一個 Binder 類的實現類,供在 onBind() 方法中返回該類的一個實例 
  52.      * @author 001718 
  53.      * 
  54.      */  
  55.     public class MyIBinder extends Binder {  
  56.         public Service getService() {  
  57.             MyServiceActivity.vh.sendMessage(MyServiceActivity.createMessage(  
  58.                     MyServiceActivity.UPDATE_VIEW,  
  59.                     "BindServiceWithIBinder.MyIBinder.getService()"));  
  60.             return BindServiceWithIBinder.this;  
  61.         }  
  62.     }  
  63.   
  64.     /** 
  65.      * service 提供的公共方法,在activity中可以調用 
  66.      */  
  67.     public void download() {  
  68.         try {  
  69.             MyServiceActivity.vh.sendMessage(MyServiceActivity.createMessage(  
  70.                     MyServiceActivity.UPDATE_VIEW, TAG  
  71.                             + " ----> download(): 文件下載中..."));  
  72.             Thread.sleep(3000);  
  73.             MyServiceActivity.vh.sendMessage(MyServiceActivity.createMessage(  
  74.                     MyServiceActivity.UPDATE_VIEW, TAG  
  75.                             + " ----> download(): 文件下載完成..."));  
  76.         } catch (InterruptedException e) {  
  77.             e.printStackTrace();  
  78.         }  
  79.     }  
  80. }  

 主 Activity 中的相應關鍵代碼為:

Java代碼  收藏代码
  1. private void doUnbindService() {  
  2.         if (isBound) {  
  3.             unbindService(myLocalServiceConnection);  
  4.             isBound = false;  
  5.         }  
  6.     }  
  7.   
  8.     private void doBindService() {  
  9.         Log.i("bind""begin to bind");  
  10.         bindService(intent, myLocalServiceConnection, Context.BIND_AUTO_CREATE);  
  11.   
  12.     }  
  13.   
  14.     private ServiceConnection myLocalServiceConnection = new ServiceConnection() {  
  15.         public void onServiceConnected(android.content.ComponentName name,  
  16.                 android.os.IBinder service) {  
  17.             MyServiceActivity.vh.sendMessage(MyServiceActivity.createMessage(  
  18.                     MyServiceActivity.UPDATE_VIEW,  
  19.                     "myServiceConnection.onServiceConnected"));  
  20.             // 因為 客戶端 與 服務 在同一個進程內,這樣一來,就可以知道參數 "service"的類型了,也就可以進行顯示的強制類型轉換了。  
  21.             // 而如果 客戶端與服務不在同一個進程中的話,那麼此處是不可以進行顯示強制類型轉換的,  
  22.             // 因為,通過Debug,可以發現此時傳進來的 Service 的類型是 BinderProxy  
  23.             MyIBinder myIBinder = (MyIBinder) service;  
  24.             bsi = (BindServiceWithIBinder) myIBinder.getService();  
  25.             isBound = true;  
  26.   
  27.             bsi.download();  
  28.         };  
  29.   
  30.         public void onServiceDisconnected(android.content.ComponentName name) {  
  31.             MyServiceActivity.vh.sendMessage(MyServiceActivity.createMessage(  
  32.                     MyServiceActivity.UPDATE_VIEW,  
  33.                     "myServiceConnection.onServiceDisconnected"));  
  34.             isBound = false;  
  35.         };  
  36.     };  

 

 下面來看運行效果:

連續點擊兩次 Bind Service



  

從此圖中可以看出,bind service 的響應過程。也可以看到,第二次點擊時,service 沒作任何反應,因為當前 Activity 在第一次點擊後就已經跟此service綁定了。

點擊 Unbind Service



 至此,該 service 的生命週期結束,它也會被系統給停掉以回收資源。

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 Felix 的頭像
    Felix

    Felix's Second Life 電腦數碼世界

    Felix 發表在 痞客邦 留言(0) 人氣()