Service介紹
Service(服務(wù))是一個可以再后臺執(zhí)行長時間運(yùn)行操作而沒有用戶界面的應(yīng)用組件吐咳。服務(wù)可用其他應(yīng)用組件啟動,服務(wù)一旦被啟動將在后臺一直運(yùn)行皆警,即使啟動服務(wù)的組件銷毀也不會影響它爽彤。
比如:服務(wù)可以處理網(wǎng)絡(luò)請求,播放音樂诉植,執(zhí)行文件I/O等,一切都可以在后臺運(yùn)行昵观。
服務(wù)的兩種形式:
- 啟動狀態(tài)
應(yīng)用組件調(diào)用startService()啟動服務(wù)晾腔,服務(wù)就處于‘啟動’狀態(tài),就可以在后臺一直運(yùn)行啊犬,除非手動停止服務(wù) - 綁定狀態(tài)
當(dāng)應(yīng)用組件通過調(diào)用bindService()綁定服務(wù)時灼擂,服務(wù)處于‘綁定’狀態(tài)。綁定服務(wù)提供一個客戶端-服務(wù)的接口觉至,運(yùn)行組件和服務(wù)進(jìn)行交互剔应。
Service使用
定義服務(wù)
public class MyTestService extends Service {
public static final String TAG = "MyTestService";
public MyTestService() {
}
/**
* 首次創(chuàng)建服務(wù)時,系統(tǒng)會執(zhí)行一次onCreate;
* 如果服務(wù)已經(jīng)啟動语御,不會再調(diào)用
*/
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
super.onCreate();
}
/**
* 每次調(diào)用startService()方法啟動服務(wù)都會被調(diào)用
* @param intent
* @param flags
* @param startId
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
/**
* 綁定服務(wù)(bindService)時才會調(diào)用
* 把Binder返回客戶端峻贮,對應(yīng)onServiceConnected的IBinder
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return new MyBinder();
}
/**
* 解除綁定時回調(diào)
* @param intent
* @return
*/
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind");
return super.onUnbind(intent);
}
/**
* 服務(wù)銷毀時回調(diào)
*/
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
}
/**
* 服務(wù)內(nèi)定義的方法,提供外部調(diào)用
*/
public void testMethod(){
Log.d(TAG, "testMethod");
}
/**
* 定義Binder對象应闯,返回客戶端使用纤控,內(nèi)部定義了一個返回服務(wù)實(shí)例的方法
*/
class MyBinder extends Binder{
/**
* 返回本服務(wù)實(shí)例(給客戶端調(diào)用)
* @return
*/
public MyTestService getServer(){
// 返回服務(wù)對象,這樣客戶端就可以調(diào)用服務(wù)的公共方法了
return MyTestService.this;
}
}
}
清單定義(應(yīng)用組件都需要在清單中定義Activity孽锥,Service, Receiver, Provider):
<service android:name=".MyTestService" android:enabled="true" android:exported="true"/>
啟動服務(wù)/停止服務(wù):
startService(new Intent(this, MyTestService.class));
stopService(new Intent(this, MyTestService.class));
服務(wù)生命周期:
onCreate() -> onStartCommand() -- 服務(wù)啟動 -- onDestory()
應(yīng)用設(shè)置那邊可以看到運(yùn)行的服務(wù):
綁定服務(wù)和解除綁定:
Intent intent = new Intent(this, MyTestService.class);
bindService(intent, cnn, BIND_AUTO_CREATE);
/**
* ServiceConnection代表與服務(wù)的連接嚼黔,
* onServiceConnected代表連接一個服務(wù)成功后被調(diào)用细层,IBinder返回服務(wù)的onBinder的對象
* onServiceDisconnected是在服務(wù)崩潰或被殺死導(dǎo)致的連接中斷時被調(diào)用惜辑,一般不會被調(diào)用
*/
ServiceConnection cnn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.d("###", "onServiceConnected");
// 獲取Binder對象
MyTestService.MyBinder binder = (MyTestService.MyBinder)iBinder;
// 調(diào)用Binder的方法,返回服務(wù)實(shí)例
myTestService = binder.getServer();
// 調(diào)用服務(wù)的方法
myTestService.testMethod();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.d("###", "onServiceDisconnected");
}
};
unbindService(cnn); // 解除綁定
生命周期:
onCreate() -> onBind() -> 服務(wù)綁定 -> onUnbind() -> onDestory()
使用綁定服務(wù)疫赎,都是為了調(diào)用服務(wù)的方法盛撑,因此在不需要的時候及時解綁防止內(nèi)存泄漏。
附上一張綁定邏輯圖:
注意:
- 這種綁定服務(wù)的方式捧搞,需要和服務(wù)在同一個進(jìn)程中抵卫,否則會調(diào)用失敗狮荔。
我們把服務(wù)設(shè)置一個進(jìn)程名::mytestservice表示包名:mytestservice
<service
android:name=".MyTestService"
android:enabled="true"
android:exported="true"
android:process=":mytestservice"/>
startService啟動服務(wù)的方式還是可以的,日志都打在服務(wù)的進(jìn)程上了介粘。
而使用綁定的方式出現(xiàn)異常:
此時跨進(jìn)程的方式需要使用Messenger和AIDL.
- 服務(wù)的執(zhí)行代碼是在主線程上的殖氏,因此不能處理太耗時的操作。如果需要耗時操作姻采,還是需要創(chuàng)建線程雅采,或者可以使用IntentService.