Android執行Service有兩種方法,一種是startService,一種是bindService。下面讓咱們一塊兒來聊一聊這兩種執行Service方法的區別。java
一、生命週期上的區別android
執行startService時,Service會經歷onCreate->onStartCommand。當執行stopService時,直接調用onDestroy方法。調用者若是沒有stopService,Service會一直在後臺運行,下次調用者再起來仍然能夠stopService。
架構
執行bindService時,Service會經歷onCreate->onBind。這個時候調用者和Service綁定在一塊兒。調用者調用unbindService方法或者調用者Context不存在了(如Activity被finish了),Service就會調用onUnbind->onDestroy。這裏所謂的綁定在一塊兒就是說二者共存亡了。ide
屢次調用startService,該Service只能被建立一次,即該Service的onCreate方法只會被調用一次。可是每次調用startService,onStartCommand方法都會被調用。Service的onStart方法在API 5時被廢棄,替代它的是onStartCommand方法。性能
第一次執行bindService時,onCreate和onBind方法會被調用,可是屢次執行bindService時,onCreate和onBind方法並不會被屢次調用,即並不會屢次建立服務和綁定服務。
this
二、調用者如何獲取綁定後的Service的方法spa
onBind回調方法將返回給客戶端一個IBinder接口實例,IBinder容許客戶端回調服務的方法,好比獲得Service運行的狀態或其餘操做。咱們須要IBinder對象返回具體的Service對象才能操做,因此說具體的Service對象必須首先實現Binder對象。
code
三、既使用startService又使用bindService的狀況xml
若是一個Service又被啓動又被綁定,則該Service會一直在後臺運行。首先無論如何調用,onCreate始終只會調用一次。對應startService調用多少次,Service的onStart方法便會調用多少次。Service的終止,須要unbindService和stopService同時調用才行。無論startService與bindService的調用順序,若是先調用unbindService,此時服務不會自動終止,再調用stopService以後,服務纔會終止;若是先調用stopService,此時服務也不會終止,而再調用unbindService或者以前調用bindService的Context不存在了(如Activity被finish的時候)以後,服務纔會自動中止。
對象
那麼,什麼狀況下既使用startService,又使用bindService呢?
若是你只是想要啓動一個後臺服務長期進行某項任務,那麼使用startService即可以了。若是你還想要與正在運行的Service取得聯繫,那麼有兩種方法:一種是使用broadcast,另外一種是使用bindService。前者的缺點是若是交流較爲頻繁,容易形成性能上的問題,然後者則沒有這些問題。所以,這種狀況就須要startService和bindService一塊兒使用了。
另外,若是你的服務只是公開一個遠程接口,供鏈接上的客戶端(Android的Service是C/S架構)遠程調用執行方法,這個時候你能夠不讓服務一開始就運行,而只是bindService,這樣在第一次bindService的時候纔會建立服務的實例運行它,這會節約不少系統資源,特別是若是你的服務是遠程服務,那麼效果會越明顯(固然在Servcie建立的是偶會花去必定時間,這點須要注意)。
四、本地服務與遠程服務
本地服務依附在主進程上,在必定程度上節約了資源。本地服務由於是在同一進程,所以不須要IPC,也不須要AIDL。相應bindService會方便不少。缺點是主進程被kill後,服務變會終止。
遠程服務是獨立的進程,對應進程名格式爲所在包名加上你指定的android:process字符串。因爲是獨立的進程,所以在Activity所在進程被kill的是偶,該服務依然在運行。缺點是該服務是獨立的進程,會佔用必定資源,而且使用AIDL進行IPC稍微麻煩一點。
對於startService來講,不論是本地服務仍是遠程服務,咱們須要作的工做都同樣簡單。
五、代碼實例
startService啓動服務
public class LocalService1 extends Service { /** * onBind 是 Service 的虛方法,所以咱們不得不實現它。 * 返回 null,表示客服端不能創建到此服務的鏈接。 */ @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); } @Override public void onStartCommand(Intent intent, int startId, int flags) { super.onStartCommand(intent, startId, flags); } @Override public void onDestroy() { super.onDestroy(); } }
bindService綁定服務
public class LocalService extends Service { /** * 在 Local Service 中咱們直接繼承 Binder 而不是 IBinder,由於 Binder 實現了 IBinder 接口,這樣咱們能夠** 少作不少工做。 */ public class SimpleBinder extends Binder{ /** * 獲取 Service 實例 * @return */ public LocalService getService(){ return LocalService.this; } public int add(int a, int b){ return a + b; } } public SimpleBinder sBinder; @Override public void onCreate() { super.onCreate(); // 建立 SimpleBinder sBinder = new SimpleBinder(); } @Override public IBinder onBind(Intent intent) { // 返回 SimpleBinder 對象 return sBinder; } }
上面的代碼關鍵之處,在於 onBind(Intent) 這個方法 返回了一個實現了 IBinder 接口的對象,這個對象將用於綁定Service 的 Activity 與 Local Service 通訊。
下面是 Activity 中的代碼:
public class Main extends Activity { private final static String TAG = "SERVICE_TEST"; private ServiceConnection sc; private boolean isBind; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); sc = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { LocalService.SimpleBinder sBinder = (LocalService.SimpleBinder)service; Log.v(TAG, "3 + 5 = " + sBinder.add(3, 5)); Log.v(TAG, sBinder.getService().toString()); } }; findViewById(R.id.btnBind).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { bindService(new Intent(Main.this, LocalService.class), sc, Context.BIND_AUTO_CREATE); isBind = true; } }); findViewById(R.id.btnUnbind).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(isBind){ unbindService(sc); isBind = false; } } }); } }
六、在AndroidManifest.xml裏Service元素常見選項
android:name ------------- 服務類名
android:label -------------- 服務的名字,若是此項不設置,那麼默認顯示的服務名則爲類名
android:icon -------------- 服務的圖標
android:permission ------- 申明此服務的權限,這意味着只有提供了該權限的應用才能控制或鏈接此服務
android:process ---------- 表示該服務是否運行在另一個進程,若是設置了此項,那麼將會在包名後面加上這段字符串表示另外一進程的名字
android:enabled ---------- 表示是否能被系統實例化,爲true表示能夠,爲false表示不能夠,默認爲true
android:exported --------- 表示該服務是否可以被其餘應用程序所控制或鏈接,不設置默認此項爲 false