服務(wù)基本上分為兩種形式
- 啟動(dòng)
當(dāng)應(yīng)用組件(如 Activity)通過(guò)調(diào)用 startService() 啟動(dòng)服務(wù)時(shí),服務(wù)即處于“啟動(dòng)”狀態(tài)。
- 綁定
當(dāng)應(yīng)用組件通過(guò)調(diào)用 [bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int)) 綁定服務(wù)時(shí),服務(wù)即處于“綁定”狀態(tài)。
綁定服務(wù)提供了一個(gè)客戶端-服務(wù)器接口,允許組件與服務(wù)進(jìn)行交互、發(fā)送請(qǐng)求、獲取結(jié)果,甚至是利用進(jìn)程間通信 (IPC) 跨進(jìn)程執(zhí)行這些操作;僅當(dāng)與另一個(gè)應(yīng)用組件綁定時(shí),綁定服務(wù)才會(huì)運(yùn)行。
應(yīng)重寫的最重要的回調(diào)方法包括:
- [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))
啟動(dòng)服務(wù)startService() -> 重寫 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int)) 一旦執(zhí)行此方法,服務(wù)即會(huì)啟動(dòng)并可在后臺(tái)無(wú)限期運(yùn)行。 如果已實(shí)現(xiàn)此方法,則在服務(wù)工作完成后,需要通過(guò)調(diào)用 stopSelf()
或stopService()來(lái)停止服務(wù)。(如果您只想提供綁定,則無(wú)需實(shí)現(xiàn)此方法。)
綁定服務(wù) [bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int)),系統(tǒng)將調(diào)用此方法onBind()。在此方法的實(shí)現(xiàn)中,必須通過(guò)返回 IBinder提供一個(gè)接口,供客戶端用來(lái)與服務(wù)進(jìn)行通信。請(qǐng)務(wù)必實(shí)現(xiàn)此方法,但如果并不希望允許綁定,則應(yīng)返回 null。
首次創(chuàng)建服務(wù)時(shí),系統(tǒng)將調(diào)用此方法來(lái)執(zhí)行一次性設(shè)置程序(在調(diào)用 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))
或 onBind()
之前)。如果服務(wù)已在運(yùn)行,則不會(huì)調(diào)用此方法。
當(dāng)服務(wù)不再使用且將被銷毀時(shí),系統(tǒng)將調(diào)用此方法。服務(wù)應(yīng)該實(shí)現(xiàn)此方法來(lái)清理所有資源,如線程、注冊(cè)的偵聽(tīng)器、接收器等。 這是服務(wù)接收的最后一個(gè)調(diào)用。
如果組件通過(guò)調(diào)用 startService()啟動(dòng)服務(wù)(這會(huì)導(dǎo)致對(duì) [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))的調(diào)用),則服務(wù)將一直運(yùn)行,直到服務(wù)使用 stopSelf()自行停止運(yùn)行,或由其他組件通過(guò)調(diào)用 stopService()停止它為止。
如果組件是通過(guò)調(diào)用 [bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int))來(lái)創(chuàng)建服務(wù)(且未調(diào)用 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))),則服務(wù)只會(huì)在該組件與其綁定時(shí)運(yùn)行。一旦該服務(wù)與所有客戶端之間的綁定全部取消,系統(tǒng)便會(huì)銷毀它。
為了確保應(yīng)用的安全性,**請(qǐng)始終使用顯式 Intent 啟動(dòng)或綁定 Service
**,且不要為服務(wù)聲明 Intent 過(guò)濾器。
創(chuàng)建啟動(dòng)服務(wù)
從傳統(tǒng)上講,可以擴(kuò)展Service , IntentService兩個(gè)類
1. Service
這是適用于所有服務(wù)的基類。擴(kuò)展此類時(shí),必須創(chuàng)建一個(gè)用于執(zhí)行所有服務(wù)工作的新線程,因?yàn)槟J(rèn)情況下,服務(wù)將使用應(yīng)用的主線程,這會(huì)降低應(yīng)用正在運(yùn)行的所有 Activity 的性能。
擴(kuò)展 Service類來(lái)創(chuàng)建啟動(dòng)服務(wù) :
該基類包含更多代碼,但如需同時(shí)處理多個(gè)啟動(dòng)請(qǐng)求,則更適合使用該基類;
使用 IntentService顯著簡(jiǎn)化了啟動(dòng)服務(wù)的實(shí)現(xiàn)。但是,若要求服務(wù)執(zhí)行多線程(而不是通過(guò)工作隊(duì)列處理啟動(dòng)請(qǐng)求),則可擴(kuò)展 Service類來(lái)處理每個(gè) Intent。
為了便于比較,以下提供了 Service 類實(shí)現(xiàn)的代碼示例,該類執(zhí)行的工作與使用 IntentService的示例完全相同。
也就是說(shuō),對(duì)于每個(gè)啟動(dòng)請(qǐng)求,它均使用工作線程執(zhí)行作業(yè),且每次僅處理一個(gè)請(qǐng)求。
以下是使用 Service類的代碼示例:
public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
long endTime = System.currentTimeMillis() + 5 * 1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}```
###2. [IntentService](http://developer.android.com/reference/android/app/IntentService.html)
這是 [Service](http://developer.android.com/reference/android/app/Service.html)的子類,它使用工作線程逐一處理所有啟動(dòng)請(qǐng)求。如果您不要求服務(wù)同時(shí)處理多個(gè)請(qǐng)求,這是最好的選擇。 您只需實(shí)現(xiàn) [onHandleIntent()](http://developer.android.com/reference/android/app/IntentService.html#onHandleIntent(android.content.Intent))方法即可,該方法會(huì)接收每個(gè)啟動(dòng)請(qǐng)求的 Intent,使您能夠執(zhí)行后臺(tái)工作。
擴(kuò)展[IntentService](http://developer.android.com/reference/android/app/IntentService.html)創(chuàng)建啟動(dòng)服務(wù),執(zhí)行以下操作:
> - 創(chuàng)建默認(rèn)的工作線程,用于在應(yīng)用的主線程外執(zhí)行傳遞給 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))的所有 Intent。
- 創(chuàng)建工作隊(duì)列,用于將一個(gè) Intent 逐一傳遞給 [onHandleIntent()](http://developer.android.com/reference/android/app/IntentService.html#onHandleIntent(android.content.Intent))實(shí)現(xiàn),這樣您就永遠(yuǎn)不必?fù)?dān)心多線程問(wèn)題。
- 在處理完所有啟動(dòng)請(qǐng)求后停止服務(wù),因此您永遠(yuǎn)不必調(diào)用 [stopSelf()](http://developer.android.com/reference/android/app/Service.html#stopSelf())。
- 提供 [onBind()](http://developer.android.com/reference/android/app/IntentService.html#onBind(android.content.Intent))的默認(rèn)實(shí)現(xiàn)(返回 null)。
- 提供 [onStartCommand()](http://developer.android.com/reference/android/app/IntentService.html#onStartCommand(android.content.Intent, int, int))的默認(rèn)實(shí)現(xiàn),可將 Intent 依次發(fā)送到工作隊(duì)列和 [onHandleIntent()](http://developer.android.com/reference/android/app/IntentService.html#onHandleIntent(android.content.Intent))實(shí)現(xiàn)。
---
綜上所述 :
只需實(shí)現(xiàn) [onHandleIntent()](http://developer.android.com/reference/android/app/IntentService.html#onHandleIntent(android.content.Intent))來(lái)完成客戶端提供的工作即可。(不過(guò),您還需要為服務(wù)提供小型構(gòu)造函數(shù)。)
以下是 [IntentService](http://developer.android.com/reference/android/app/IntentService.html)的實(shí)現(xiàn)示例:
```java
public class HelloIntentService extends IntentService {
public HelloIntentService() {
super("HelloIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
long endTime = System.currentTimeMillis() + 5 * 1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
-- 您只需要一個(gè)構(gòu)造函數(shù)和一個(gè) onHandleIntent()實(shí)現(xiàn)即可。
如果您決定還重寫其他回調(diào)方法(如 onCreate()、[onStartCommand()](http://developer.android.com/reference/android/app/IntentService.html#onStartCommand(android.content.Intent, int, int))或 onDestroy()),請(qǐng)確保調(diào)用超類實(shí)現(xiàn),以便 IntentService能夠妥善處理工作線程的生命周期。
例如,[onStartCommand()](http://developer.android.com/reference/android/app/IntentService.html#onStartCommand(android.content.Intent, int, int))必須返回默認(rèn)實(shí)現(xiàn)(即,如何將 Intent 傳遞給 onHandleIntent()):
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
除 onHandleIntent()之外,您無(wú)需從中調(diào)用超類的唯一方法就是 onBind()
(僅當(dāng)服務(wù)允許綁定時(shí),才需要實(shí)現(xiàn)該方法)。
啟動(dòng)服務(wù)
可以通過(guò)將 [Intent](http://developer.android.com/reference/android/content/Intent.html)(指定要啟動(dòng)的服務(wù))傳遞給 startService(),從 Activity 或其他應(yīng)用組件啟動(dòng)服務(wù)。Android 系統(tǒng)調(diào)用服務(wù)的 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))
方法,并向其傳遞 Intent。(切勿直接調(diào)用[onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))。)
例如,Activity 可以結(jié)合使用顯式 Intent 與 startService()
,啟動(dòng)上文中的示例服務(wù) (HelloSevice):
ntent intent = new Intent(this, HelloService.class);startService(intent);
startService()方法將立即返回,且 Android 系統(tǒng)調(diào)用服務(wù)的 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))方法。如果服務(wù)尚未運(yùn)行,則系統(tǒng)會(huì)先調(diào)用 onCreate(),然后再調(diào)用 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))。
如果服務(wù)亦未提供綁定,則使用 startService()傳遞的 Intent 是應(yīng)用組件與服務(wù)之間唯一的通信模式。但是,如果您希望服務(wù)返回結(jié)果,則啟動(dòng)服務(wù)的客戶端可以為廣播創(chuàng)建一個(gè) PendingIntent(使用[getBroadcast()](http://developer.android.com/reference/android/app/PendingIntent.html#getBroadcast(android.content.Context, int, android.content.Intent, int))),并通過(guò)啟動(dòng)服務(wù)的 Intent傳遞給服務(wù)。然后,服務(wù)就可以使用廣播傳遞結(jié)果。
多個(gè)服務(wù)啟動(dòng)請(qǐng)求會(huì)導(dǎo)致多次對(duì)服務(wù)的 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))進(jìn)行相應(yīng)的調(diào)用。但是,要停止服務(wù),只需一個(gè)服務(wù)停止請(qǐng)求(使用 stopSelf() 或 stopService())即可。
停止服務(wù)
啟動(dòng)服務(wù)必須管理自己的生命周期。也就是說(shuō),除非系統(tǒng)必須回收內(nèi)存資源,否則系統(tǒng)不會(huì)停止或銷毀服務(wù),而且服務(wù)在 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))返回后會(huì)繼續(xù)運(yùn)行。因此,服務(wù)必須通過(guò)調(diào)用 stopSelf()
自行停止運(yùn)行,或者由另一個(gè)組件通過(guò)調(diào)用 stopService()來(lái)停止它。
一旦請(qǐng)求使用 stopSelf()或 stopService()停止服務(wù),系統(tǒng)就會(huì)盡快銷毀服務(wù)。
但是,如果服務(wù)同時(shí)處理多個(gè) [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))請(qǐng)求,則您不應(yīng)在處理完一個(gè)啟動(dòng)請(qǐng)求之后停止服務(wù),因?yàn)槟赡芤呀?jīng)收到了新的啟動(dòng)請(qǐng)求(在第一個(gè)請(qǐng)求結(jié)束時(shí)停止服務(wù)會(huì)終止第二個(gè)請(qǐng)求)。為了避免這一問(wèn)題,您可以使用 stopSelf(int)確保服務(wù)停止請(qǐng)求始終基于最近的啟動(dòng)請(qǐng)求。也就說(shuō),在調(diào)用 stopSelf(int)時(shí),傳遞與停止請(qǐng)求的 ID 對(duì)應(yīng)的啟動(dòng)請(qǐng)求的 ID(傳遞給 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))的 startId) 。然后,如果在您能夠調(diào)用stopSelf(int)之前服務(wù)收到了新的啟動(dòng)請(qǐng)求, ID 就不匹配,服務(wù)也就不會(huì)停止。
注意:為了避免浪費(fèi)系統(tǒng)資源和消耗電池電量,應(yīng)用必須在工作完成之后停止其服務(wù)。 如有必要,其他組件可以通過(guò)調(diào)用 stopService()來(lái)停止服務(wù)。即使為服務(wù)啟用了綁定,一旦服務(wù)收到對(duì) [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))的調(diào)用,您始終仍須親自停止服務(wù)。
創(chuàng)建綁定服務(wù)
綁定服務(wù)允許應(yīng)用組件通過(guò)調(diào)用 [bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int))與其綁定,以便創(chuàng)建長(zhǎng)期連接(通常不允許組件通過(guò)調(diào)用startService()來(lái)啟動(dòng)它)。
如需與 Activity 和其他應(yīng)用組件中的服務(wù)進(jìn)行交互,或者需要通過(guò)進(jìn)程間通信 (IPC) 向其他應(yīng)用公開(kāi)某些應(yīng)用功能,則應(yīng)創(chuàng)建綁定服務(wù)。
要?jiǎng)?chuàng)建綁定服務(wù),必須實(shí)現(xiàn) onBind()回調(diào)方法以返回 IBinder,用于定義與服務(wù)通信的接口。然后,其他應(yīng)用組件可以調(diào)用 [bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int))來(lái)檢索該接口,并開(kāi)始對(duì)服務(wù)調(diào)用方法。服務(wù)只用于與其綁定的應(yīng)用組件,因此如果沒(méi)有組件綁定到服務(wù),則系統(tǒng)會(huì)銷毀服務(wù)(您不必按通過(guò) [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))
啟動(dòng)的服務(wù)那樣來(lái)停止綁定服務(wù))。
要?jiǎng)?chuàng)建綁定服務(wù),首先必須定義指定客戶端如何與服務(wù)通信的接口。 服務(wù)與客戶端之間的這個(gè)接口必須是IBinder的實(shí)現(xiàn),并且服務(wù)必須從 onBind()回調(diào)方法返回它。一旦客戶端收到 IBinder
,即可開(kāi)始通過(guò)該接口與服務(wù)進(jìn)行交互。
多個(gè)客戶端可以同時(shí)綁定到服務(wù)。客戶端完成與服務(wù)的交互后,會(huì)調(diào)用 unbindService()
取消綁定。一旦沒(méi)有客戶端綁定到該服務(wù),系統(tǒng)就會(huì)銷毀它。
有多種方法實(shí)現(xiàn)綁定服務(wù),其實(shí)現(xiàn)比啟動(dòng)服務(wù)更為復(fù)雜,因此綁定服務(wù)將在有關(guān)綁定服務(wù)的單獨(dú)文檔中專門討論。
向用戶發(fā)送通知
一旦運(yùn)行起來(lái),服務(wù)即可使用 Toast 通知或狀態(tài)欄通知來(lái)通知用戶所發(fā)生的事件。
Toast 通知是指出現(xiàn)在當(dāng)前窗口的表面、片刻隨即消失不見(jiàn)的消息,而狀態(tài)欄通知?jiǎng)t在狀態(tài)欄提供內(nèi)含消息的圖標(biāo),用戶可以選擇該圖標(biāo)來(lái)采取操作(例如啟動(dòng) Activity)。
通常,當(dāng)某些后臺(tái)工作已經(jīng)完成(例如文件下載完成)且用戶現(xiàn)在可以對(duì)其進(jìn)行操作時(shí),狀態(tài)欄通知是最佳方法。 當(dāng)用戶從展開(kāi)視圖中選定通知時(shí),通知即可啟動(dòng) Activity(例如查看已下載的文件)。
如需了解詳細(xì)信息,請(qǐng)參閱 Toast 通知或狀態(tài)欄通知開(kāi)發(fā)者指南。
在前臺(tái)運(yùn)行服務(wù)
前臺(tái)服務(wù)被認(rèn)為是用戶主動(dòng)意識(shí)到的一種服務(wù),因此在內(nèi)存不足時(shí),系統(tǒng)也不會(huì)考慮將其終止。 前臺(tái)服務(wù)必須為狀態(tài)欄提供通知,狀態(tài)欄位于“正在進(jìn)行”標(biāo)題下方,這意味著除非服務(wù)停止或從前臺(tái)刪除,否則不能清除通知。
例如,應(yīng)該將從服務(wù)播放音樂(lè)的音樂(lè)播放器設(shè)置為在前臺(tái)運(yùn)行,這是因?yàn)橛脩裘鞔_意識(shí)到其操作。 狀態(tài)欄中的通知可能表示正在播放的歌曲,并允許用戶啟動(dòng) Activity 來(lái)與音樂(lè)播放器進(jìn)行交互。
要請(qǐng)求讓服務(wù)運(yùn)行于前臺(tái),請(qǐng)調(diào)用 [startForeground()](http://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification))。此方法取兩個(gè)參數(shù):唯一標(biāo)識(shí)通知的整型數(shù)和狀態(tài)欄的 Notification。例如:
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
注意:提供給 [startForeground()](http://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification))的整型 ID 不得為 0
要從前臺(tái)刪除服務(wù),請(qǐng)調(diào)用 stopForeground()。此方法取一個(gè)布爾值,指示是否也刪除狀態(tài)欄通知。 此方法絕對(duì)不會(huì)停止服務(wù)。
但是,如果您在服務(wù)正在前臺(tái)運(yùn)行時(shí)將其停止,則通知也會(huì)被刪除。
如需了解有關(guān)通知的詳細(xì)信息,請(qǐng)參閱創(chuàng)建狀態(tài)欄通知。
管理服務(wù)生命周期
服務(wù)的生命周期比 Activity 的生命周期要簡(jiǎn)單得多。但是,密切關(guān)注如何創(chuàng)建和銷毀服務(wù)反而更加重要,因?yàn)榉?wù)可以在用戶沒(méi)有意識(shí)到的情況下運(yùn)行于后臺(tái)。
服務(wù)生命周期(從創(chuàng)建到銷毀)可以遵循兩條不同的路徑:
啟動(dòng)服務(wù)
該服務(wù)在其他組件調(diào)用 startService()時(shí)創(chuàng)建,然后無(wú)限期運(yùn)行,且必須通過(guò)調(diào)用 stopSelf()來(lái)自行停止運(yùn)行。此外,其他組件也可以通過(guò)調(diào)用 stopService()來(lái)停止服務(wù)。服務(wù)停止后,系統(tǒng)會(huì)將其銷毀。綁定服務(wù)
該服務(wù)在另一個(gè)組件(客戶端)調(diào)用 [bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int))時(shí)創(chuàng)建。然后,客戶端通過(guò) IBinder接口與服務(wù)進(jìn)行通信。客戶端可以通過(guò)調(diào)用 unbindService()關(guān)閉連接。多個(gè)客戶端可以綁定到相同服務(wù),而且當(dāng)所有綁定全部取消后,系統(tǒng)即會(huì)銷毀該服務(wù)。 (服務(wù)不必自行停止運(yùn)行。)
這兩條路徑并非完全獨(dú)立。也就是說(shuō),您可以綁定到已經(jīng)使用 startService()啟動(dòng)的服務(wù)。例如,可以通過(guò)使用 Intent(標(biāo)識(shí)要播放的音樂(lè))調(diào)用 startService()來(lái)啟動(dòng)后臺(tái)音樂(lè)服務(wù)。隨后,可能在用戶需要稍加控制播放器或獲取有關(guān)當(dāng)前播放歌曲的信息時(shí),Activity 可以通過(guò)調(diào)用 [bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int))綁定到服務(wù)。在這種情況下,除非所有客戶端均取消綁定,否則 stopService() 或 stopSelf()不會(huì)真正停止服務(wù)。
實(shí)現(xiàn)生命周期回調(diào)
與 Activity 類似,服務(wù)也擁有生命周期回調(diào)方法,您可以實(shí)現(xiàn)這些方法來(lái)監(jiān)控服務(wù)狀態(tài)的變化并適時(shí)執(zhí)行工作。 以下框架服務(wù)展示了每種生命周期方法:
public class ExampleService extends Service {
int mStartMode; // indicates how to behave if the service is killed
IBinder mBinder; // interface for clients that bind
boolean mAllowRebind; // indicates whether onRebind should be used
@Override
public void onCreate() {
// The service is being created
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The service is starting, due to a call to startService()
return mStartMode;
}
@Override
public IBinder onBind(Intent intent) {
// A client is binding to the service with bindService()
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// All clients have unbound with unbindService()
return mAllowRebind;
}
@Override
public void onRebind(Intent intent) {
// A client is binding to the service with bindService(),
// after onUnbind() has already been called
}
@Override
public void onDestroy() {
// The service is no longer used and is being destroyed
}
}
注:與 Activity 生命周期回調(diào)方法不同,您不需要調(diào)用這些回調(diào)方法的超類實(shí)現(xiàn)。
服務(wù)生命周期左圖顯示了使用 startService()所創(chuàng)建的服務(wù)的生命周期,右圖顯示了使用 [bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int))所創(chuàng)建的服務(wù)的生命周期。
通過(guò)實(shí)現(xiàn)這些方法,您可以監(jiān)控服務(wù)生命周期的兩個(gè)嵌套循環(huán):
- 服務(wù)的 整個(gè)生命周期 從調(diào)用 onCreate()開(kāi)始起,到 onDestroy()返回時(shí)結(jié)束。與 Activity 類似,服務(wù)也在 onCreate()中完成初始設(shè)置,并在 onDestroy()中釋放所有剩余資源。例如,音樂(lè)播放服務(wù)可以在onCreate()中創(chuàng)建用于播放音樂(lè)的線程,然后在 onDestroy()中停止該線程。無(wú)論服務(wù)是通過(guò) startService()還是 [bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int))創(chuàng)建,都會(huì)為所有服務(wù)調(diào)用 onCreate()和onDestroy()方法。
- 服務(wù)的 有效生命周期 從調(diào)用 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))或 onBind()方法開(kāi)始。每種方法均有 Intent對(duì)象,該對(duì)象分別傳遞到 startService()或 [bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int))。對(duì)于啟動(dòng)服務(wù),有效生命周期與整個(gè)生命周期同時(shí)結(jié)束(即便是在 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))返回之后,服務(wù)仍然處于活動(dòng)狀態(tài))。對(duì)于綁定服務(wù),有效生命周期在 onUnbind()返回時(shí)結(jié)束
注:盡管啟動(dòng)服務(wù)是通過(guò)調(diào)用 stopSelf()或 stopService()來(lái)停止,但是該服務(wù)并無(wú)相應(yīng)的回調(diào)(沒(méi)有onStop()回調(diào))。因此,除非服務(wù)綁定到客戶端,否則在服務(wù)停止時(shí),系統(tǒng)會(huì)將其銷毀—onDestroy()是接收到的唯一回調(diào)。
上圖說(shuō)明了服務(wù)的典型回調(diào)方法。盡管該圖分開(kāi)介紹通過(guò) startService()創(chuàng)建的服務(wù)和通過(guò)[bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int))創(chuàng)建的服務(wù),但是請(qǐng)記住,不管啟動(dòng)方式如何,任何服務(wù)均有可能允許客戶端與其綁定。因此,最初用 [onStartCommand()](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent, int, int))(通過(guò)客戶端調(diào)用 startService())啟動(dòng)的服務(wù)仍可接收對(duì) onBind()的調(diào)用(當(dāng)客戶端調(diào)用 [bindService()](http://developer.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int))時(shí))。
如需了解有關(guān)創(chuàng)建提供綁定的服務(wù)的詳細(xì)信息,請(qǐng)參閱綁定服務(wù)文檔,該文檔的管理綁定服務(wù)的生命周期部分提供了有關(guān) onRebind()回調(diào)方法的更多信息。