Android startservice & bindservice的區別
作爲一個android開發者,service大家應該已經接觸過了,接觸Android的第一節課,就是將Android的四大組件,那麼作爲四大組件之一的service,你是否足夠了解呢?
service和thread的區別你是否知道?service真的能執行長時間的後臺操作麼?
你是否知道startservice和bindservice的區別呢?
service的生命週期,我們是否應該主動結束一個service呢?service是否會導致內存泄露呢?
- service與intentservice的區別是什麼?
上邊是關於service的一些問題,問題1,我們已經在之前的博客上講解過,詳細內容見博客http://blog.csdn.net/u014088294/article/details/49907385
關於問題4,也可以參考我們之前的文章 ,http://blog.csdn.net/u014088294/article/details/44279399
我們主要解答問題2,startservice與bindservice的區別。
Developer上提到,service主要有兩種形式,
- started
- bound
上邊的started呢,對應與startservice,bound對應於bindservice,他們都是啓動service的方式。
startservice
我們可以通過startservice來啓動一個service,啓動後,service在後臺運行。通常來說,該service是無法返回結果的(這也是與bindservice的區別之一),比如我們可以下載一個文件。
和startservice對應的是stopservice,我們可以來顯式的結束一個service。
service的生命週期也比較簡單,和startservice相關的有三個函數,分別是onCreate,onStartCommand,onDestory。
當我們首次startserivce啓動一個service的時候,會調用service的onCreate函數,創建該服務,然後調用onStartCommand函數,執行操作。如果我們多次通過startservice啓動服務,那麼onCreate只會調用一次,直接調用onStartCommand。
我們可以調用stopsevice來結束一個service。同樣,我們也可以多次調用(第一次調用已經結束,但是後來繼續調用並不會產生異常)。
當一個service通過startservice啓動後,它就獨立於調用者而運行(也就是說,調用者的生命週期和它的生命週期沒有關係),因此呢,service應該在任務完成的時候調用stopSelf函數或者調用者stopservice來結束該服務。
Developer上提到,當我們的service執行完的時候,爲了避免消耗系統資源或電量,應該結束該service。否則,該服務將會一直運行在後臺,直到設備內存不足等原因把他關閉掉。
然而,startservice並不能解決我們所有的需求,比如,我有時候,需要service的返回結果,我需要和service交互,startservice顯然不能完成。那麼我們可以使用到bindservice
bindservice
Developer這樣提到,
A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC).
我們可以利用bindservice來和service綁定,綁定後,我們可以和service交互,發送請求,得到結果甚至執行IPC通信。
那麼,我們應該如何使用bindservice呢?
- 首先我們需要重載service的onBinder,返回一個IBinder對象。該對象是
調用者和serivce交互的接口。 - 新建一個ServiceConnection變量,該類是監聽Service是否bound的接口,我們重載其onServiceConnected和onServiceDisconnected方法。onServiceConnected方法中,我們得到了Service中onBinder返回的IBinder接口。
- 調用bindservice來綁定服務。
按照上邊的步驟,我們的代碼如下,
1. 重載onBinder並返回一個IBinder對象。在LocalBinder中,提供getSercive方法,返回service實例。
public class LocalBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
private final IBinder mBinder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return mBinder;
}
2.調用者中新建ServiceConnection接口,在onServiceConnected方法中,將IBinder對象轉爲LocalBinder對象,並調用其getService方法,得到Service。
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mBoundService = ((MyService.LocalBinder) service).getService();
}
public void onServiceDisconnected(ComponentName className) {
mBoundService = null;
}
};
3.調用者執行bindservice,其中mConnection爲ServiceConnection接口。
bindService(new Intent(MainActivity.this,MyService.class), mConnection, Context.BIND_AUTO_CREATE);
當用戶執行bindservice後,bind的結果會回調mConnection接口,若bind成功,就會回調onServiceConnected方法,然後我們在此方法中,得到了Service實例,得到Service實例後,然後我們就可以和Service交互了。
我們繼續完善代碼,在Service的onCreate方法中,我們新建一個線程,每隔1s,計數器加1.其中count爲成員變量,表示當前計數值,threadDisable表示是否service關閉。
new Thread(new Runnable() {
// @Override
public void run() {
while (!threadDisable) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
count++;
System.out.println("CountService Count is " + count);
}
}
}).start();
然後,我們在Service中新建一個方法,返回計數值。
public int getCount() {
return count;
}
那麼我們在調用者中,就可以利用上邊得到的mBoundService來調用getCount方法,達到與service交互的目的。
項目地址,https://github.com/KingPaul/ServiceDemo