小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

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

 lifei_szdz 2013-01-26


bound服務(wù)是客戶端-服務(wù)器模式的服務(wù)。bound服務(wù)允許組件(比如activity)對其進(jìn)行綁定、發(fā)送請求、接收響應(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ù)。不過,通常你還應(yīng)該參考 Services 文檔以獲取關(guān)于服務(wù)的更多信息,比如如何從服務(wù)中發(fā)送通知、如何將服務(wù)設(shè)置為前臺(tái)運(yùn)行等等。

簡介

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

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

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

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

請確保已經(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 對象,此對象定義了客戶端與服務(wù)進(jìn)行交互時(shí)所需的編程接口。

客戶端可以通過調(diào)用 bindService() 方法來綁定服務(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ù)上。不過,只有在第一個(gè)客戶端綁定時(shí),系統(tǒng)才會(huì)調(diào)用服務(wù)的 onBind() 方法來獲取 IBinder 。然后,系統(tǒng)會(huì)向后續(xù)請求綁定的客戶端傳送這同一個(gè) IBinder ,而不再調(diào)用 onBind() 。

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

當(dāng)你實(shí)現(xiàn)自己的bound服務(wù)時(shí),最重要的工作就是定義 onBind() 回調(diào)方法所返回的接口。定義服務(wù) IBinder 接口的方式有好幾種,后續(xù)章節(jié)將會(huì)對每種技術(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)該通過擴(kuò)展 Binder 類來創(chuàng)建你的接口,并從 onBind() 返回一個(gè)它的實(shí)例??蛻舳私邮赵?Binder 對象并用它來直接訪問 Binder 甚至 Service 中可用的公共(public)方法。

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

2、使用Messenger

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

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

3、使用AIDL

Android接口定義語言AIDL(Android Interface Definition Language) 完成以下的所有工作:將對象解析為操作系統(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è)包含了所有客戶端請求的隊(duì)列,這樣服務(wù)每次就只會(huì)收到一個(gè)請求。 可是,如果想讓你的服務(wù)能同時(shí)處理多個(gè)請求,那你就可以直接使用AIDL。 這種情況下,你的服務(wù)必須擁有多線程處理能力,并且是以線程安全的方式編寫的。

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

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

擴(kuò)展Binder類

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

注意: 僅當(dāng)客戶端和服務(wù)位于同一個(gè)應(yīng)用程序和進(jìn)程中,這也是最常見的情況,這種方式才會(huì)有用。 比如,一個(gè)音樂應(yīng)用需要把一個(gè)activity綁定到它自己的后臺(tái)音樂播放服務(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 并用所提供的方法對綁定的服務(wù)進(jìn)行調(diào)用。

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

比如,以下是一個(gè)服務(wù)的示例,它通過實(shí)現(xiàn)一個(gè) Binder 來為客戶端訪問它內(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中的方法。
            // 不過,如果該調(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了,對IBinder進(jìn)行類型轉(zhuǎn)換(cast)并獲得LocalService對象的實(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ù)綁定過程的信息。

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

更多示例代碼,請參閱 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ù)的請求放入一個(gè)隊(duì)列。而純粹的AIDL接口會(huì)把這些請求同時(shí)發(fā)送給服務(wù),這樣服務(wù)就必須要能夠多線程運(yùn)行。

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

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

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

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

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

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

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();
    }
}

請注意 Handler 中的 handleMessage() 方法,這里是服務(wù)接收輸入消息 Message 的地方,也是根據(jù) what 數(shù)字來決定要執(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ù)交互的對象。
            // 我們將用一個(gè)Messenger來與服務(wù)進(jìn)行通信,
            // 因此這里我們獲取到一個(gè)原始IBinder對象的客戶端實(shí)例。
            mService = new Messenger(service);
            mBound = true;
        }
 
        public void onServiceDisconnected(ComponentName className) {
            // 當(dāng)與服務(wù)的聯(lián)接被意外中斷時(shí)——也就是說服務(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;
        }
    }
}

請注意,上述例子中沒有給出服務(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)用程序組件(客戶端)可以通過調(diào)用 bindService() 來綁定服務(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)用該方法來傳遞客戶端所需的那個(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)用該方法來傳遞服務(wù)的 onBind() 方法所返回的 IBinder 。
    • onServiceDisconnected() 當(dāng)與服務(wù)的聯(lián)接發(fā)生意外中斷時(shí),比如服務(wù)崩潰或者被殺死時(shí),Android系統(tǒng)將會(huì)調(diào)用該方法??蛻舳私獬壎〞r(shí),不會(huì)調(diào)用該方法。
  2. 調(diào)用 bindService() ,傳入已實(shí)現(xiàn)的 ServiceConnection 。
  3. 當(dāng)系統(tǒng)調(diào)用你的 onServiceConnected() 回調(diào)方法時(shí),你可以利用接口中定義的方法開始對服務(wù)的調(diào)用。
  4. 要斷開與服務(wù)的聯(lián)接,請調(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)為LocalService類,并獲取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í)體類并直接訪問它。
      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 對象。
  • 第三個(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ì)拋出的異常。
  • 對象的引用計(jì)數(shù)是跨進(jìn)程的。
  • 你通常應(yīng)該成對地進(jìn)行綁定和解除綁定,并與客戶端生命周期的啟動(dòng)和結(jié)束過程相呼應(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() 中解除綁定。請注意這表明你的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ù)的示例代碼,請參閱 piDemos 中的 RemoteService.java 類。

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

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

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

此外,如果你的服務(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ù)生命周期的更多信息,請參閱 Services 文檔 。

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多