乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Android開發(fā)者指南 -Bound服務(wù)

       lifei_szdz 2013-01-26


      bound服務(wù)是客戶端-服務(wù)器模式的服務(wù)。bound服務(wù)允許組件(比如activity)對(duì)其進(jìn)行綁定、發(fā)送請(qǐng)求、接收響應(yīng)、甚至進(jìn)行進(jìn)程間通信(IPC)。 bound服務(wù)一般只在為其它應(yīng)用程序組件服務(wù)期間才是存活的,而不會(huì)一直在后臺(tái)保持運(yùn)行。

      本文展示了如何創(chuàng)建一個(gè)bound服務(wù),包括如何從其它應(yīng)用程序組件綁定到該服務(wù)。不過(guò),通常你還應(yīng)該參考 Services 文檔以獲取關(guān)于服務(wù)的更多信息,比如如何從服務(wù)中發(fā)送通知、如何將服務(wù)設(shè)置為前臺(tái)運(yùn)行等等。

      簡(jiǎn)介

      綁定到一個(gè)started服務(wù)

      正如 Services 一文中所述,你可以創(chuàng)建一個(gè)同時(shí)支持started和bound的服務(wù)。也就是說(shuō),服務(wù)可以通過(guò)調(diào)用 startService() 來(lái)啟動(dòng),這使它一直保持運(yùn)行,同時(shí)它也允許客戶端通過(guò)調(diào)用 bindService() 來(lái)與之綁定。

      如果你的服務(wù)確實(shí)可以是started和bound的,那么服務(wù)啟動(dòng)后,系統(tǒng)將不會(huì)在所有客戶端解除綁定時(shí)銷毀它。取而代之的是,你必須通過(guò)調(diào)用 stopSelf() 或 stopService() 顯式終止此服務(wù)。

      雖然你通常應(yīng)該要實(shí)現(xiàn) onBind() 或 onStartCommand() 中的一個(gè),但有時(shí)需要同時(shí)實(shí)現(xiàn)兩者。 比如,音樂(lè)播放器的服務(wù)也許就需要同時(shí)實(shí)現(xiàn)后臺(tái)運(yùn)行和支持綁定。 這樣,activity就可以啟動(dòng)服務(wù)來(lái)播放音樂(lè),并且音樂(lè)會(huì)一直播放下去,即使用戶離開該應(yīng)用程序也沒關(guān)系,這個(gè)activity可以綁定播放服務(wù)來(lái)重新獲得播放控制權(quán)。

      請(qǐng)確保已經(jīng)閱讀了 管理Bound服務(wù)的生命周期 章節(jié),以獲取更多向started服務(wù)添加綁定時(shí)的服務(wù)生命周期的有關(guān)信息。

      bound服務(wù)是 Service 類的一種實(shí)現(xiàn),它允許其它應(yīng)用程序與其綁定并交互。為了讓服務(wù)支持綁定,你必須實(shí)現(xiàn) onBind() 回調(diào)方法。這個(gè)方法返回一個(gè) IBinder 對(duì)象,此對(duì)象定義了客戶端與服務(wù)進(jìn)行交互時(shí)所需的編程接口。

      客戶端可以通過(guò)調(diào)用 bindService() 方法來(lái)綁定服務(wù)。在調(diào)用時(shí),必須提供一個(gè) ServiceConnection 的實(shí)現(xiàn)代碼,用于監(jiān)控與服務(wù)的聯(lián)接。 bindService() 將會(huì)立即返回,沒有返回值。但是Android系統(tǒng)在創(chuàng)建客戶端與服務(wù)之間的聯(lián)接時(shí),會(huì)調(diào)用 ServiceConnection 中的 onServiceConnected() 方法,傳遞一個(gè) IBinder ,客戶端將用它與服務(wù)進(jìn)行通信。

      多個(gè)客戶端可以同時(shí)聯(lián)接到一個(gè)服務(wù)上。不過(guò),只有在第一個(gè)客戶端綁定時(shí),系統(tǒng)才會(huì)調(diào)用服務(wù)的 onBind() 方法來(lái)獲取 IBinder 。然后,系統(tǒng)會(huì)向后續(xù)請(qǐng)求綁定的客戶端傳送這同一個(gè) IBinder ,而不再調(diào)用 onBind() 。

      當(dāng)最后一個(gè)客戶端解除綁定后,系統(tǒng)會(huì)銷毀服務(wù)(除非服務(wù)同時(shí)是通過(guò) startService() 啟動(dòng)的)。

      當(dāng)你實(shí)現(xiàn)自己的bound服務(wù)時(shí),最重要的工作就是定義 onBind() 回調(diào)方法所返回的接口。定義服務(wù) IBinder 接口的方式有好幾種,后續(xù)章節(jié)將會(huì)對(duì)每種技術(shù)進(jìn)行 創(chuàng)建一個(gè)支持綁定的服務(wù)時(shí),你必須提供一個(gè) IBinder ,用作客戶端和服務(wù)間進(jìn)行通信的編程接口。定義這類接口的方式有三種:

      1、擴(kuò)展Binder類

      如果服務(wù)是你的應(yīng)用程序所私有的,并且與客戶端運(yùn)行于同一個(gè)進(jìn)程中(通常都是如此),你應(yīng)該通過(guò)擴(kuò)展 Binder 類來(lái)創(chuàng)建你的接口,并從 onBind() 返回一個(gè)它的實(shí)例??蛻舳私邮赵?Binder 對(duì)象并用它來(lái)直接訪問(wèn) Binder 甚至 Service 中可用的公共(public)方法。

      如果你的服務(wù)只是為你自己的應(yīng)用程序執(zhí)行一些后臺(tái)工作,那這就是首選的技術(shù)方案。不用這種方式來(lái)創(chuàng)建接口的理由只有一個(gè),就是服務(wù)要被其它應(yīng)用程序使用或者要跨多個(gè)進(jìn)程使用。

      2、使用Messenger

      如果你需要接口跨越多個(gè)進(jìn)程進(jìn)行工作,可以通過(guò) Messenger 來(lái)為服務(wù)創(chuàng)建接口。在這種方式下,服務(wù)定義一個(gè)響應(yīng)各類消息對(duì)象 Message 的 Handler 。此 Handler 是 Messenger 與客戶端共享同一個(gè) IBinder 的基礎(chǔ),它使得客戶端可以用消息對(duì)象 Message 向服務(wù)發(fā)送指令。此外,客戶端還可以定義自己的 Message ,以便服務(wù)能夠往回發(fā)送消息。

      這是執(zhí)行進(jìn)程間通信(IPC)最為簡(jiǎn)便的方式,因?yàn)?Messenger 會(huì)把所有的請(qǐng)求放入一個(gè)獨(dú)立進(jìn)程中的隊(duì)列,這樣你就不一定非要把服務(wù)設(shè)計(jì)為線程安全的模式了。

      3、使用AIDL

      Android接口定義語(yǔ)言AIDL(Android Interface Definition Language) 完成以下的所有工作:將對(duì)象解析為操作系統(tǒng)可識(shí)別的原始形態(tài),并將它們跨進(jìn)程序列化(marshal)以完成IPC。 前一個(gè)使用 Messenger 的方式,實(shí)際上也是基于AIDL的,它用AIDL作為底層結(jié)構(gòu)。如上所述, Messenger 將在一個(gè)單獨(dú)的進(jìn)程中創(chuàng)建一個(gè)包含了所有客戶端請(qǐng)求的隊(duì)列,這樣服務(wù)每次就只會(huì)收到一個(gè)請(qǐng)求。 可是,如果想讓你的服務(wù)能同時(shí)處理多個(gè)請(qǐng)求,那你就可以直接使用AIDL。 這種情況下,你的服務(wù)必須擁有多線程處理能力,并且是以線程安全的方式編寫的。

      要直接使用AIDL,你必須創(chuàng)建一個(gè).aidl文件,其中定義了編程的接口。 Android SDK 工具使用此文件來(lái)生成一個(gè)抽象類(abstract class),其中實(shí)現(xiàn)了接口及對(duì)IPC的處理,然后你就可以在自己的服務(wù)中擴(kuò)展該類。

      注意: 絕大多數(shù)應(yīng)用程序都不應(yīng)該用AIDL來(lái)創(chuàng)建bound服務(wù),因?yàn)檫@可能需要多線程處理能力并且會(huì)讓代碼變得更為復(fù)雜。 因此,AIDL對(duì)絕大多數(shù)應(yīng)用程序都不適用,并且本文也不會(huì)討論如何在服務(wù)中使用它的內(nèi)容。如果你確信需要直接使用AIDL,那請(qǐng)參閱 AIDL 文檔。

      擴(kuò)展Binder類

      如果你的服務(wù)只用于本地應(yīng)用程序并且不需要跨進(jìn)程工作,那你只要實(shí)現(xiàn)自己的 Binder 類即可,這樣你的客戶端就能直接訪問(wèn)服務(wù)中的公共方法了。

      注意: 僅當(dāng)客戶端和服務(wù)位于同一個(gè)應(yīng)用程序和進(jìn)程中,這也是最常見的情況,這種方式才會(huì)有用。 比如,一個(gè)音樂(lè)應(yīng)用需要把一個(gè)activity綁定到它自己的后臺(tái)音樂(lè)播放服務(wù)上,采用這種方式就會(huì)很不錯(cuò)。

      以下是設(shè)置步驟:

      1. 在你的服務(wù)中,創(chuàng)建一個(gè) Binder 的實(shí)例,其中實(shí)現(xiàn)以下三者之一:
        1. 包含了可供客戶端調(diào)用的公共方法
        2. 返回當(dāng)前 Service 實(shí)例,其中包含了可供客戶端調(diào)用的公共方法。
        3. 或者,返回內(nèi)含服務(wù)類的其它類的一個(gè)實(shí)例,服務(wù)中包含了可供客戶端調(diào)用的公共方法。
      2. 從回調(diào)方法 onBind() 中返回 Binder 的該實(shí)例。
      3. 在客戶端中,在回調(diào)方法 onServiceConnected() 中接收 Binder 并用所提供的方法對(duì)綁定的服務(wù)進(jìn)行調(diào)用。

      注意: 服務(wù)和客戶端之所以必須位于同一個(gè)應(yīng)用程序中,是為了讓客戶端能夠正確轉(zhuǎn)換(cast)返回的對(duì)象并調(diào)用對(duì)象的API。 服務(wù)和客戶端也必須位于同一個(gè)進(jìn)程中,因?yàn)檫@種方式不能執(zhí)行任何跨進(jìn)程的序列化(marshalling)操作。

      比如,以下是一個(gè)服務(wù)的示例,它通過(guò)實(shí)現(xiàn)一個(gè) Binder 來(lái)為客戶端訪問(wèn)它內(nèi)部的方法提供支持:

      public class LocalService extends Service {
          // 給客戶端的Binder
          private final IBinder mBinder = new LocalBinder();
          // 生成隨機(jī)數(shù)
          private final Random mGenerator = new Random();
       
       
          public class LocalBinder extends Binder {
              LocalService getService() {
                  // Return this instance of LocalService so clients can call public methods
                  return LocalService.this;
              }
          }
       
          @Override
          public IBinder onBind(Intent intent) {
              return mBinder;
          }
       
       
          public int getRandomNumber() {
            return mGenerator.nextInt(100);
          }
      }

      LocalBinder為客戶端提供了getService()方法,用于返回當(dāng)前LocalService的實(shí)例。 這就讓客戶端可以調(diào)用服務(wù)中的公共方法。比如,客戶端可以調(diào)用服務(wù)中的getRandomNumber()。

      以下是一個(gè)綁定到LocalService的activity,當(dāng)點(diǎn)擊按鈕時(shí),它會(huì)調(diào)用getRandomNumber():

      public class BindingActivity extends Activity {
          LocalService mService;
          boolean mBound = false;
       
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.main);
          }
       
          @Override
          protected void onStart() {
              super.onStart();
              // 綁定到LocalService
              Intent intent = new Intent(this, LocalService.class);
              bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
          }
       
          @Override
          protected void onStop() {
              super.onStop();
              // 與服務(wù)解除綁定
              if (mBound) {
                  unbindService(mConnection);
                  mBound = false;
              }
          }
       
       
          public void onButtonClick(View v) {
              if (mBound) {
                  // 調(diào)用LocalService中的方法。
                  // 不過(guò),如果該調(diào)用會(huì)導(dǎo)致某些操作的掛起,那么調(diào)用應(yīng)該放入單獨(dú)的線程中進(jìn)行,
                  // 以免降低activity的性能。
                  int num = mService.getRandomNumber();
                  Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
              }
          }
       
       
          private ServiceConnection mConnection = new ServiceConnection() {
       
              @Override
              public void onServiceConnected(ComponentName className,
                      IBinder service) {
                  // 我們已經(jīng)綁定到LocalService了,對(duì)IBinder進(jìn)行類型轉(zhuǎn)換(cast)并獲得LocalService對(duì)象的實(shí)例
                  LocalBinder binder = (LocalBinder) service;
                  mService = binder.getService();
                  mBound = true;
              }
       
              @Override
              public void onServiceDisconnected(ComponentName arg0) {
                  mBound = false;
              }
          };
      }

      上述例子展示了客戶端如何利用 ServiceConnectiononServiceConnected() 回調(diào)方法綁定到服務(wù)。下一節(jié)將給出更多有關(guān)服務(wù)綁定過(guò)程的信息。

      注意: 上述例子并沒有明確地解除綁定,但所有的客戶端都應(yīng)該適時(shí)地解除綁定(比如activity暫停pause時(shí))。

      更多示例代碼,請(qǐng)參閱 ApiDemos 中的 LocalService.java 類和 LocalServiceActivities.java 類。

      使用Messenger

      與AIDL相比

      當(dāng)你需要進(jìn)行IPC時(shí),使用 Messenger 要比用AIDL實(shí)現(xiàn)接口要容易些,因?yàn)?Messenger 會(huì)把所有調(diào)用服務(wù)的請(qǐng)求放入一個(gè)隊(duì)列。而純粹的AIDL接口會(huì)把這些請(qǐng)求同時(shí)發(fā)送給服務(wù),這樣服務(wù)就必須要能夠多線程運(yùn)行。

      對(duì)于絕大多數(shù)應(yīng)用程序而言,服務(wù)沒有必要多線程運(yùn)行,因此利用 Messenger 可以讓服務(wù)一次只處理一個(gè)調(diào)用。如果 你的服務(wù)非要多線程運(yùn)行,那你就應(yīng)該用 AIDL 來(lái)定義接口。

      如果你的服務(wù)需要與遠(yuǎn)程進(jìn)程進(jìn)行通信,那你可以使用一個(gè) Messenger 來(lái)提供服務(wù)的接口。這種技術(shù)能讓你無(wú)需使用AIDL就能進(jìn)行進(jìn)程間通信(IPC)。

      以下概括了 Messenger 的使用方法:

      • 服務(wù)實(shí)現(xiàn)一個(gè) Handler ,用于客戶端每次調(diào)用時(shí)接收回調(diào)。
      • 此 Handler 用于創(chuàng)建一個(gè) Messenger 對(duì)象(它是一個(gè)對(duì) Handler 的引用)。
      • 此 Messenger 對(duì)象創(chuàng)建一個(gè) IBinder ,服務(wù)在 onBind() 中把它返回給客戶端。
      • 客戶端用 IBinder 將 Messenger (引用服務(wù)的 Handler )實(shí)例化,客戶端用它向服務(wù)發(fā)送消息對(duì)象 Message 。
      • 服務(wù)接收 Handler 中的每個(gè)消息 Message ——確切的說(shuō),是在 handleMessage() 方法中接收。

      通過(guò)這種方式,客戶端不需要調(diào)用服務(wù)中的“方法”。取而代之的是,客戶端發(fā)送“消息”( Message 對(duì)象),服務(wù)則接收位于 Handler 中的這個(gè)消息。

      以下是服務(wù)使用一個(gè) Messenger 做為接口的簡(jiǎn)單例子:

      public class MessengerService extends Service {
       
          static final int MSG_SAY_HELLO = 1;
       
          class IncomingHandler extends Handler {
              @Override
              public void handleMessage(Message msg) {
                  switch (msg.what) {
                      case MSG_SAY_HELLO:
                          Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                          break;
                      default:
                          super.handleMessage(msg);
                  }
              }
          }
       
          final Messenger mMessenger = new Messenger(new IncomingHandler());
       
          @Override
          public IBinder onBind(Intent intent) {
              Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
              return mMessenger.getBinder();
          }
      }

      請(qǐng)注意 Handler 中的 handleMessage() 方法,這里是服務(wù)接收輸入消息 Message 的地方,也是根據(jù) what 數(shù)字來(lái)決定要執(zhí)行什么操作的地方。

      客戶端要做的全部工作就是根據(jù)服務(wù)返回的 IBinder 創(chuàng)建一個(gè) Messenger ,并用 send() 方法發(fā)送一個(gè)消息。例如,以下是一個(gè)activity示例,它綁定到上述服務(wù),并向服務(wù)發(fā)送 MSG_SAY_HELLO消息:

      public class ActivityMessenger extends Activity {
       
          Messenger mService = null;    
          boolean mBound;
       
          private ServiceConnection mConnection = new ServiceConnection() {
              public void onServiceConnected(ComponentName className, IBinder service) {
                  // 與服務(wù)建立聯(lián)接后將會(huì)調(diào)用本方法,
                  // 給出用于和服務(wù)交互的對(duì)象。
                  // 我們將用一個(gè)Messenger來(lái)與服務(wù)進(jìn)行通信,
                  // 因此這里我們獲取到一個(gè)原始IBinder對(duì)象的客戶端實(shí)例。
                  mService = new Messenger(service);
                  mBound = true;
              }
       
              public void onServiceDisconnected(ComponentName className) {
                  // 當(dāng)與服務(wù)的聯(lián)接被意外中斷時(shí)——也就是說(shuō)服務(wù)的進(jìn)程崩潰了,
                  // 將會(huì)調(diào)用本方法。
                  mService = null;
                  mBound = false;
              }
          };
       
          public void sayHello(View v) {
              if (!mBound) return;
              // 創(chuàng)建并向服務(wù)發(fā)送一個(gè)消息,用到了已約定的'what'值
              Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
              try {
                  mService.send(msg);
              } catch (RemoteException e) {
                  e.printStackTrace();
              }
          }
       
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.main);
          }
       
          @Override
          protected void onStart() {
              super.onStart();
              // 綁定服務(wù)
              bindService(new Intent(this, MessengerService.class), mConnection,
                  Context.BIND_AUTO_CREATE);
          }
       
          @Override
          protected void onStop() {
              super.onStop();
              // 解綁服務(wù)
              if (mBound) {
                  unbindService(mConnection);
                  mBound = false;
              }
          }
      }

      請(qǐng)注意,上述例子中沒有給出服務(wù)是如何響應(yīng)客戶端的。如果你需要服務(wù)進(jìn)行響應(yīng),那你還需要在客戶端創(chuàng)建一個(gè) Messenger 。然后,當(dāng)客戶端接收到 onServiceConnected() 回調(diào)后,它再發(fā)送一個(gè)消息 Message 給服務(wù),消息的 send() 方法中的 replyTo 參數(shù)里包含了客戶端的 Messenger 。

      MessengerService.java (服務(wù))和 MessengerServiceActivities.java (客戶端)例程中,你可以看到如何雙向發(fā)送消息的例子。

      綁定一個(gè)服務(wù)

      應(yīng)用程序組件(客戶端)可以通過(guò)調(diào)用 bindService() 來(lái)綁定服務(wù)。然后Android系統(tǒng)會(huì)調(diào)用服務(wù)的 onBind() 方法,返回一個(gè)用于和服務(wù)進(jìn)行交互的 IBinder 。

      綁定是異步進(jìn)行的。 bindService() 將立即返回,并不會(huì)向客戶端返回 IBinder 。為了接收 IBinder ,客戶端必須創(chuàng)建一個(gè) ServiceConnection 的實(shí)例,并把它傳給 bindService() 。 ServiceConnection 包含了一個(gè)回調(diào)方法,系統(tǒng)將會(huì)調(diào)用該方法來(lái)傳遞客戶端所需的那個(gè) IBinder 。

      注意: 只有activity、服務(wù)和content provider才可以綁定到服務(wù)上——你不能從廣播接收器(broadcast receiver)中綁定服務(wù)。

      因此,要把客戶端綁定到服務(wù)上,你必須:

      1. 實(shí)現(xiàn) ServiceConnection 。你的實(shí)現(xiàn)代碼必須重寫兩個(gè)回調(diào)方法:
        • onServiceConnected() 系統(tǒng)調(diào)用該方法來(lái)傳遞服務(wù)的 onBind() 方法所返回的 IBinder 。
        • onServiceDisconnected() 當(dāng)與服務(wù)的聯(lián)接發(fā)生意外中斷時(shí),比如服務(wù)崩潰或者被殺死時(shí),Android系統(tǒng)將會(huì)調(diào)用該方法。客戶端解除綁定時(shí),不會(huì)調(diào)用該方法。
      2. 調(diào)用 bindService() ,傳入已實(shí)現(xiàn)的 ServiceConnection 。
      3. 當(dāng)系統(tǒng)調(diào)用你的 onServiceConnected() 回調(diào)方法時(shí),你可以利用接口中定義的方法開始對(duì)服務(wù)的調(diào)用。
      4. 要斷開與服務(wù)的聯(lián)接,請(qǐng)調(diào)用 unbindService() 。

      當(dāng)客戶端被銷毀時(shí),與服務(wù)的綁定也將解除。但與服務(wù)交互完畢后,或者你的activity進(jìn)入pause狀態(tài)時(shí),你都應(yīng)該確保解除綁定,以便服務(wù)能夠在用完后及時(shí)關(guān)閉。 (綁定和解除綁定的合適時(shí)機(jī)將在后續(xù)章節(jié)中繼續(xù)討論。)

      例如,以下代碼段將客戶端與前面 擴(kuò)展Binder類 創(chuàng)建的服務(wù)聯(lián)接,而要做的全部工作就是把返回的 IBinder 轉(zhuǎn)換(cast)為L(zhǎng)ocalService類,并獲取LocalService的實(shí)例:

      LocalService mService;
      private ServiceConnection mConnection = new ServiceConnection() {
          // 與服務(wù)的聯(lián)接建立之后將會(huì)調(diào)用
          public void onServiceConnected(ComponentName className, IBinder service) {
              // 因?yàn)槲覀円呀?jīng)與明顯是運(yùn)行于同一進(jìn)程中的服務(wù)建立了聯(lián)接,
              // 我們就可以把它的IBinder轉(zhuǎn)換為一個(gè)實(shí)體類并直接訪問(wèn)它。
            LocalBinder binder = (LocalBinder) service;
              mService = binder.getService();
              mBound = true;
          }
       
          // 與服務(wù)的聯(lián)接意外中斷時(shí)將會(huì)調(diào)用
          public void onServiceDisconnected(ComponentName className) {
              Log.e(TAG, "onServiceDisconnected");
              mBound = false;
          }
      };

      利用這個(gè) ServiceConnection ,客戶端就能夠把它傳入 bindService() 完成與服務(wù)的綁定。例如:

      Intent intent = new Intent(this, LocalService.class);
      bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
      • bindService() 的第一個(gè)參數(shù)是一個(gè) Intent ,它明確給出了要綁定的服務(wù)名稱(注意intent可以是隱式的)。
      • 第二個(gè)參數(shù)是 ServiceConnection 對(duì)象。
      • 第三個(gè)參數(shù)是一個(gè)指明綁定選項(xiàng)的標(biāo)志。通常應(yīng)該是 BIND_AUTO_CREATE ,表示如果服務(wù)未啟動(dòng)的話則創(chuàng)建服務(wù)。其它可能的值包括 BIND_DEBUG_UNBIND 和 BIND_NOT_FOREGROUND ,或者為0表示不指定。

      其它注意事項(xiàng)

      以下是有關(guān)綁定服務(wù)的一些重要注意事項(xiàng):

      • 你應(yīng)該確保捕獲 DeadObjectException 異常,當(dāng)聯(lián)接中斷時(shí)會(huì)拋出該異常。這是遠(yuǎn)程方法唯一會(huì)拋出的異常。
      • 對(duì)象的引用計(jì)數(shù)是跨進(jìn)程的。
      • 你通常應(yīng)該成對(duì)地進(jìn)行綁定和解除綁定,并與客戶端生命周期的啟動(dòng)和結(jié)束過(guò)程相呼應(yīng)。比如:
        • 如果僅當(dāng)你的activity可見時(shí)才需要與服務(wù)進(jìn)行交互,則你應(yīng)該在 onStart() 中進(jìn)行綁定,并在 onStop() 中解除綁定。
        • 如果你的activity需要在stopped后并進(jìn)入后臺(tái)期間仍然能接收響應(yīng),則你可以在 onCreate() 中進(jìn)行綁定,并在 onDestroy() 中解除綁定。請(qǐng)注意這表明你的activity在整個(gè)運(yùn)行期間都需要使用服務(wù)(即使在后臺(tái)),因此假如服務(wù)位于其它進(jìn)程中,則你會(huì) 增加進(jìn)程所耗費(fèi)的資源,進(jìn)程也會(huì)更容易被系統(tǒng)殺死。

      注意: 你通常不應(yīng)該在activity的 onResume() 和 onPause() 中綁定和解除綁定,因?yàn)檫@兩個(gè)回調(diào)方法在每次切換生命周期狀態(tài)時(shí)都會(huì)發(fā)生,這時(shí)你應(yīng)該讓處理工作最少化。 而且,如果應(yīng)用程序中有多個(gè)activity都綁定到同一個(gè)服務(wù)上,則在兩個(gè)activity間切換時(shí)都會(huì)發(fā)生狀態(tài)轉(zhuǎn)換, 因?yàn)楫?dāng)前activity解除綁定(在pause時(shí))后,緊接著下一個(gè)activity又會(huì)進(jìn)行綁定(resume時(shí)),所以服務(wù)也許在銷毀后馬上就要重建。 (這種activity狀態(tài)轉(zhuǎn)換、多個(gè)activity間的生命周期協(xié)作在 Activities 文檔中描述。)

      更多展示綁定服務(wù)的示例代碼,請(qǐng)參閱 piDemos 中的 RemoteService.java 類。

      管理Bound服務(wù)的生命周期

      一旦服務(wù)被所有客戶端解除綁定,則Android系統(tǒng)將會(huì)銷毀它(除非它同時(shí)又是用 onStartCommand() started)。因此,如果你的服務(wù)就是一個(gè)純粹的bound服務(wù),那你就不需要管理它的生命周期——Android系統(tǒng)會(huì)替你管理,根據(jù)是否還有客戶端對(duì)其綁定即可。

      不過(guò),如果你選擇實(shí)現(xiàn) onStartCommand() 回調(diào)方法,那么你就必須顯式地終止服務(wù),因?yàn)榇朔?wù)現(xiàn)在已經(jīng)被視為started了。這種情況下,無(wú)論是否還存在客戶端與其綁定,此服務(wù)都會(huì)運(yùn)行下去,直至自行用 stopSelf() 終止或由其它組件調(diào)用 stopService() 來(lái)終止。

      此外,如果你的服務(wù)是started且允許被綁定,那么系統(tǒng)調(diào)用你的 onUnbind() 方法時(shí),你可以選擇返回true。這樣作的結(jié)果就是,下次客戶端綁定時(shí)將會(huì)收到 onRebind() 調(diào)用(而不是收到 onBind() 調(diào)用)。 onRebind() 返回void,但客戶端仍然能在它的 onServiceConnected() 回調(diào)方法中收到 IBinder 。圖1展示了這種生命周期的運(yùn)行邏輯。

      關(guān)于started服務(wù)生命周期的更多信息,請(qǐng)參閱 Services 文檔 。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多