Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Service詳解

Android Service詳解

編輯:關於Android編程

來自:https://developer.android.com/guide/components/services.html

Service是一個可以在後台執行長時間運行操作而不使用用戶界面的應用組件。服務可由其他應用組件啟動,而且即使用戶切換到其他應用,服務仍將在後台繼續運行。 此外,組件可以綁定到服務,以與之進行交互,甚至是執行進程間通信 (IPC)。 例如,服務可以處理網絡事務、播放音樂,執行文件 I/O 或與內容提供程序交互,而所有這一切均可在後台進行。

服務基本上分為兩種形式:

啟動

當應用組件(如 Activity)通過調用startService()啟動服務時,服務即處於“啟動”狀態。一旦啟動,服務即可在後台無限期運行,即使啟動服務的組件已被銷毀也不受影響。 已啟動的服務通常是執行單一操作,而且不會將結果返回給調用方。例如,它可能通過網絡下載或上傳文件。 操作完成後,服務會自行停止運行。

綁定

當應用組件通過調用bindService()綁定到服務時,服務即處於“綁定”狀態。綁定服務提供了一個客戶端-服務器接口,允許組件與服務進行交互、發送請求、獲取結果,甚至是利用進程間通信 (IPC) 跨進程執行這些操作。 僅當與另一個應用組件綁定時,綁定服務才會運行。 多個組件可以同時綁定到該服務,但全部取消綁定後,該服務即會被銷毀。

雖然本文檔是分開概括討論這兩種服務,但是您的服務可以同時以這兩種方式運行,也就是說,它既可以是啟動服務(以無限期運行),也允許綁定。問題只是在於您是否實現了一組回調方法:onStartCommand()(允許組件啟動服務)和onBind()(允許綁定服務)。

無論應用是處於啟動狀態還是綁定狀態,抑或處於啟動並且綁定狀態,任何應用組件均可像使用活動那樣通過調用Intent來使用服務(即使此服務來自另一應用)。 不過,您可以通過清單文件將服務聲明為私有服務,並阻止其他應用訪問。使用清單文件聲明服務部分將對此做更詳盡的闡述。

注意:服務在其托管進程的主線程中運行,它既不創建自己的線程,也不在單獨的進程中運行(除非另行指定)。 這意味著,如果服務將執行任何 CPU 密集型工作或阻止性操作(例如 MP3 播放或聯網),則應在服務內創建新線程來完成這項工作。通過使用單獨的線程,可以降低發生“應用無響應”(ANR) 錯誤的風險,而應用的主線程仍可繼續專注於運行用戶與 Activity 之間的交互。

基礎知識

要創建服務,您必須創建Service的子類(或使用它的一個現有子類)。在實現中,您需要重寫一些回調方法,以處理服務生命周期的某些關鍵方面並提供一種機制將組件綁定到服務(如適用)。 應重寫的最重要的回調方法包括:

onStartCommand()

當另一個組件(如 Activity)通過調用startService()請求啟動服務時,系統將調用此方法。一旦執行此方法,服務即會啟動並可在後台無限期運行。 如果您實現此方法,則在服務工作完成後,需要由您通過調用stopSelf()或stopService()來停止服務。(如果您只想提供綁定,則無需實現此方法。)

onBind()

當另一個組件想通過調用bindService()與服務綁定(例如執行 RPC)時,系統將調用此方法。在此方法的實現中,您必須通過返回IBinder提供一個接口,供客戶端用來與服務進行通信。請務必實現此方法,但如果您並不希望允許綁定,則應返回 null。

onCreate()

首次創建服務時,系統將調用此方法來執行一次性設置程序(在調用onStartCommand()或onBind()之前)。如果服務已在運行,則不會調用此方法。

onDestroy()

當服務不再使用且將被銷毀時,系統將調用此方法。服務應該實現此方法來清理所有資源,如線程、注冊的偵聽器、接收器等。 這是服務接收的最後一個調用。

如果組件通過調用startService()啟動服務(這會導致對onStartCommand()的調用),則服務將一直運行,直到服務使用stopSelf()自行停止運行,或由其他組件通過調用stopService()停止它為止。

如果組件是通過調用bindService()來創建服務(且未調用onStartCommand()),則服務只會在該組件與其綁定時運行。一旦該服務與所有客戶端之間的綁定全部取消,系統便會銷毀它。

僅當內存過低且必須回收系統資源以供具有用戶焦點的 Activity 使用時,Android 系統才會強制停止服務。如果將服務綁定到具有用戶焦點的 Activity,則它不太可能會終止;如果將服務聲明為在前台運行(稍後討論),則它幾乎永遠不會終止。或者,如果服務已啟動並要長時間運行,則系統會隨著時間的推移降低服務在後台任務列表中的位置,而服務也將隨之變得非常容易被終止;如果服務是啟動服務,則您必須將其設計為能夠妥善處理系統對它的重啟。 如果系統終止服務,那麼一旦資源變得再次可用,系統便會重啟服務(不過這還取決於從onStartCommand()返回的值,本文稍後會對此加以討論)。如需了解有關系統會在何時銷毀服務的詳細信息,請參閱進程和線程文檔。

在下文中,您將了解如何創建各類服務以及如何從其他應用組件使用服務。

您應使用服務還是線程?

簡單地說,服務是一種即使用戶未與應用交互,但它仍可以在後台運行的組件。 因此,您應僅在必要時才創建服務。

如需在主線程外部執行工作,不過只是在用戶正在與應用交互時才有此需要,則應創建新線程而非服務。 例如,如果您只是想在 Activity 運行的同時播放一些音樂,則可在onCreate()中創建線程,在onStart()中啟動線程,然後在onStop()中停止線程。您還可以考慮使用AsyncTask或HandlerThread,而非傳統的Thread類。如需了解有關線程的詳細信息,請參閱進程和線程文檔。

請記住,如果您確實要使用服務,則默認情況下,它仍會在應用的主線程中運行,因此,如果服務執行的是密集型或阻止性操作,則您仍應在服務內創建新線程。

使用清單文件聲明服務

如同 Activity(以及其他組件)一樣,您必須在應用的清單文件中聲明所有服務。

要聲明服務,請添加元素作為元素的子元素。例如:

...

...

如需了解有關使用清單文件聲明服務的詳細信息,請參閱元素參考文檔。

您還可將其他屬性包括在元素中,以定義一些特性,如啟動服務及其運行所在進程所需的權限。android:name屬性是唯一必需的屬性,用於指定服務的類名。應用一旦發布,即不應更改此類名,如若不然,可能會存在因依賴顯式 Intent 啟動或綁定服務而破壞代碼的風險(請閱讀博客文章Things That Cannot Change[不能更改的內容])。

為了確保應用的安全性,請始終使用顯式 Intent 啟動或綁定Service,且不要為服務聲明 Intent 過濾器。 啟動哪個服務存在一定的不確定性,而如果對這種不確定性的考量非常有必要,則可為服務提供 Intent 過濾器並從Intent中排除相應的組件名稱,但隨後必須使用setPackage()方法設置 Intent 的軟件包,這樣可以充分消除目標服務的不確定性。

此外,還可以通過添加android:exported屬性並將其設置為"false",確保服務僅適用於您的應用。這可以有效阻止其他應用啟動您的服務,即便在使用顯式 Intent 時也如此。

創建啟動服務

啟動服務由另一個組件通過調用startService()啟動,這會導致調用服務的onStartCommand()方法。

服務啟動之後,其生命周期即獨立於啟動它的組件,並且可以在後台無限期地運行,即使啟動服務的組件已被銷毀也不受影響。 因此,服務應通過調用stopSelf()結束工作來自行停止運行,或者由另一個組件通過調用stopService()來停止它。

應用組件(如 Activity)可以通過調用startService()方法並傳遞Intent對象 (指定服務並包含待使用服務的所有數據)來啟動服務。服務通過onStartCommand()方法接收此Intent。

例如,假設某 Activity 需要將一些數據保存到在線數據庫中。該 Activity 可以啟動一個協同服務,並通過向startService()傳遞一個 Intent,為該服務提供要保存的數據。服務通過onStartCommand()接收 Intent,連接到 Internet 並執行數據庫事務。事務完成之後,服務會自行停止運行並隨即被銷毀。

注意:默認情況下,服務與服務聲明所在的應用運行於同一進程,而且運行於該應用的主線程中。 因此,如果服務在用戶與來自同一應用的 Activity 進行交互時執行密集型或阻止性操作,則會降低 Activity 性能。 為了避免影響應用性能,您應在服務內啟動新線程。

從傳統上講,您可以擴展兩個類來創建啟動服務:

Service

這是適用於所有服務的基類。擴展此類時,必須創建一個用於執行所有服務工作的新線程,因為默認情況下,服務將使用應用的主線程,這會降低應用正在運行的所有 Activity 的性能。

IntentService

這是Service的子類,它使用工作線程逐一處理所有啟動請求。如果您不要求服務同時處理多個請求,這是最好的選擇。 您只需實現onHandleIntent()方法即可,該方法會接收每個啟動請求的 Intent,使您能夠執行後台工作。

下文介紹如何使用其中任一類實現服務。

擴展 IntentService 類

由於大多數啟動服務都不必同時處理多個請求(實際上,這種多線程情況可能很危險),因此使用IntentService類實現服務也許是最好的選擇。

IntentService執行以下操作:

創建默認的工作線程,用於在應用的主線程外執行傳遞給onStartCommand()的所有 Intent。

創建工作隊列,用於將一個 Intent 逐一傳遞給onHandleIntent()實現,這樣您就永遠不必擔心多線程問題。

在處理完所有啟動請求後停止服務,因此您永遠不必調用stopSelf()。

提供onBind()的默認實現(返回 null)。

提供onStartCommand()的默認實現,可將 Intent 依次發送到工作隊列和onHandleIntent()實現。

綜上所述,您只需實現onHandleIntent()來完成客戶端提供的工作即可。(不過,您還需要為服務提供小型構造函數。)

以下是IntentService的實現示例:

public class HelloIntentService extends IntentService {

/**

* A constructor is required, and must call the super IntentService(String)

* constructor with a name for the worker thread.

*/

public HelloIntentService() {

super("HelloIntentService");

}

/**

* The IntentService calls this method from the default worker thread with

* the intent that started the service. When this method returns, IntentService

* stops the service, as appropriate.

*/

@Override

protected void onHandleIntent(Intent intent) {

// Normally we would do some work here, like download a file.

// For our sample, we just sleep for 5 seconds.

long endTime = System.currentTimeMillis() + 5*1000;

while (System.currentTimeMillis() < endTime) {

synchronized (this) {

try {

wait(endTime - System.currentTimeMillis());

} catch (Exception e) {

}

}

}

}

}

您只需要一個構造函數和一個onHandleIntent()實現即可。

如果您決定還重寫其他回調方法(如onCreate()、onStartCommand()或onDestroy()),請確保調用超類實現,以便IntentService能夠妥善處理工作線程的生命周期。

例如,onStartCommand()必須返回默認實現(即,如何將 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()之外,您無需從中調用超類的唯一方法就是onBind()(僅當服務允許綁定時,才需要實現該方法)。

在下一部分中,您將了解如何在擴展Service基類時實現同類服務。該基類包含更多代碼,但如需同時處理多個啟動請求,則更適合使用該基類。

擴展服務類

正如上一部分中所述,使用IntentService顯著簡化了啟動服務的實現。但是,若要求服務執行多線程(而不是通過工作隊列處理啟動請求),則可擴展Service類來處理每個 Intent。

為了便於比較,以下提供了Service類實現的代碼示例,該類執行的工作與上述使用IntentService的示例完全相同。也就是說,對於每個啟動請求,它均使用工作線程執行作業,且每次僅處理一個請求。

以下代碼說明:每次啟動這個服務,都會調用onStartCommand方法,然後發送消息給工作線程隊列,所以是串行執行。其實IntentService底層就是使用HandlerThread+Handler實現的,所以下面代碼就是IntentService源碼!

public class HelloService extends Service {

private Looper mServiceLooper;

private ServiceHandler mServiceHandler;

// Handler that receives messages from the thread

private final class ServiceHandler extends Handler {

public ServiceHandler(Looper looper) {

super(looper);

}

@Override

public void handleMessage(Message msg) {

// Normally we would do some work here, like download a file.

// For our sample, we just sleep for 5 seconds.

long endTime = System.currentTimeMillis() + 5*1000;

while (System.currentTimeMillis() < endTime) {

synchronized (this) {

try {

wait(endTime - System.currentTimeMillis());

} catch (Exception e) {

}

}

}

// Stop the service using the startId, so that we don't stop

// the service in the middle of handling another job

stopSelf(msg.arg1);

}

}

@Override

public void onCreate() {

// Start up the thread running the service. Note that we create a

// separate thread because the service normally runs in the process's

// main thread, which we don't want to block. We also make it

// background priority so CPU-intensive work will not disrupt our UI.

HandlerThread thread = new HandlerThread("ServiceStartArguments",

Process.THREAD_PRIORITY_BACKGROUND);

thread.start();

// Get the HandlerThread's Looper and use it for our Handler

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

// For each start request, send a message to start a job and deliver the

// start ID so we know which request we're stopping when we finish the job

Message msg = mServiceHandler.obtainMessage();

msg.arg1 = startId;

mServiceHandler.sendMessage(msg);

// If we get killed, after returning from here, restart

return START_STICKY;

}

@Override

public IBinder onBind(Intent intent) {

// We don't provide binding, so return null

return null;

}

@Override

public void onDestroy() {

Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();

}

}

正如您所見,與使用IntentService相比,這需要執行更多工作。

但是,因為是由您自己處理對onStartCommand()的每個調用,因此可以同時執行多個請求。此示例並未這樣做,但如果您希望如此,則可為每個請求創建一個新線程,然後立即運行這些線程(而不是等待上一個請求完成)。

請注意,onStartCommand()方法必須返回整型數。整型數是一個值,用於描述系統應該如何在服務終止的情況下繼續運行服務(如上所述,IntentService的默認實現將為您處理這種情況,不過您可以對其進行修改)。從onStartCommand()返回的值必須是以下常量之一:

START_NOT_STICKY

如果系統在onStartCommand()返回後終止服務,則除非有掛起 Intent 要傳遞,否則系統不會重建服務。這是最安全的選項,可以避免在不必要時以及應用能夠輕松重啟所有未完成的作業時運行服務。

START_STICKY

如果系統在onStartCommand()返回後終止服務,則會重建服務並調用onStartCommand(),但絕對不會重新傳遞最後一個 Intent。相反,除非有掛起 Intent 要啟動服務(在這種情況下,將傳遞這些 Intent ),否則系統會通過空 Intent 調用onStartCommand()。這適用於不執行命令、但無限期運行並等待作業的媒體播放器(或類似服務)。

START_REDELIVER_INTENT

如果系統在onStartCommand()返回後終止服務,則會重建服務,並通過傳遞給服務的最後一個 Intent 調用onStartCommand()。任何掛起 Intent 均依次傳遞。這適用於主動執行應該立即恢復的作業(例如下載文件)的服務。

有關這些返回值的更多詳細信息,請查閱每個常量鏈接的參考文檔。

啟動服務

您可以通過將Intent(指定要啟動的服務)傳遞給startService(),從 Activity 或其他應用組件啟動服務。Android 系統調用服務的onStartCommand()方法,並向其傳遞Intent。(切勿直接調用onStartCommand()。)

例如,Activity 可以結合使用顯式 Intent 與startService(),啟動上文中的示例服務 (HelloSevice):

Intent intent = new Intent(this, HelloService.class);

startService(intent);

startService()方法將立即返回,且 Android 系統調用服務的onStartCommand()方法。如果服務尚未運行,則系統會先調用onCreate(),然後再調用onStartCommand()。

如果服務亦未提供綁定,則使用startService()傳遞的 Intent 是應用組件與服務之間唯一的通信模式。但是,如果您希望服務返回結果,則啟動服務的客戶端可以為廣播創建一個PendingIntent(使用getBroadcast()),並通過啟動服務的Intent傳遞給服務。然後,服務就可以使用廣播傳遞結果。

多個服務啟動請求會導致多次對服務的onStartCommand()進行相應的調用。但是,要停止服務,只需一個服務停止請求(使用stopSelf()或stopService())即可。

停止服務

但是,如果服務同時處理多個onStartCommand()請求,則您不應在處理完一個啟動請求之後停止服務,因為您可能已經收到了新的啟動請求(在第一個請求結束時停止服務會終止第二個請求)。為了避免這一問題,您可以使用stopSelf(int)確保服務停止請求始終基於最近的啟動請求。也就說,在調用stopSelf(int)時,傳遞與停止請求的 ID 對應的啟動請求的 ID(傳遞給onStartCommand()的startId) 。然後,如果在您能夠調用stopSelf(int)之前服務收到了新的啟動請求, ID 就不匹配,服務也就不會停止。

注意:為了避免浪費系統資源和消耗電池電量,應用必須在工作完成之後停止其服務。 如有必要,其他組件可以通過調用stopService()來停止服務。即使為服務啟用了綁定,一旦服務收到對onStartCommand()的調用,您始終仍須親自停止服務。

如需了解有關服務生命周期的詳細信息,請參閱下面有關管理服務生命周期的部分

創建綁定服務

綁定服務允許應用組件通過調用bindService()與其綁定,以便創建長期連接(通常不允許組件通過調用startService()來啟動它)。

如需與 Activity 和其他應用組件中的服務進行交互,或者需要通過進程間通信 (IPC) 向其他應用公開某些應用功能,則應創建綁定服務。

要創建綁定服務,必須實現onBind()回調方法以返回IBinder,用於定義與服務通信的接口。然後,其他應用組件可以調用bindService()來檢索該接口,並開始對服務調用方法。服務只用於與其綁定的應用組件,因此如果沒有組件綁定到服務,則系統會銷毀服務(您不必按通過onStartCommand()啟動的服務那樣來停止綁定服務)。

要創建綁定服務,首先必須定義指定客戶端如何與服務通信的接口。 服務與客戶端之間的這個接口必須是IBinder的實現,並且服務必須從onBind()回調方法返回它。一旦客戶端收到IBinder,即可開始通過該接口與服務進行交互。

多個客戶端可以同時綁定到服務。客戶端完成與服務的交互後,會調用unbindService()取消綁定。一旦沒有客戶端綁定到該服務,系統就會銷毀它。

有多種方法實現綁定服務,其實現比啟動服務更為復雜,因此綁定服務將在有關綁定服務的單獨文檔中專門討論。

向用戶發送通知

一旦運行起來,服務即可使用Toast 通知或狀態欄通知來通知用戶所發生的事件。

Toast 通知是指出現在當前窗口的表面、片刻隨即消失不見的消息,而狀態欄通知則在狀態欄提供內含消息的圖標,用戶可以選擇該圖標來采取操作(例如啟動 Activity)。

通常,當某些後台工作已經完成(例如文件下載完成)且用戶現在可以對其進行操作時,狀態欄通知是最佳方法。 當用戶從展開視圖中選定通知時,通知即可啟動 Activity(例如查看已下載的文件)。

如需了解詳細信息,請參閱Toast 通知或狀態欄通知開發者指南。

在前台運行服務

前台服務被認為是用戶主動意識到的一種服務,因此在內存不足時,系統也不會考慮將其終止。 前台服務必須為狀態欄提供通知,狀態欄位於“正在進行”標題下方,這意味著除非服務停止或從前台刪除,否則不能清除通知。

例如,應該將從服務播放音樂的音樂播放器設置為在前台運行,這是因為用戶明確意識到其操作。 狀態欄中的通知可能表示正在播放的歌曲,並允許用戶啟動 Activity 來與音樂播放器進行交互。(音樂播放器都是這樣做的,比如酷狗和QQ音樂)

要請求讓服務運行於前台,請調用startForeground()。此方法取兩個參數:唯一標識通知的整型數和狀態欄的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()的整型 ID 不得為 0。

要從前台刪除服務,請調用stopForeground()。此方法取一個布爾值,指示是否也刪除狀態欄通知。 此方法絕對不會停止服務。但是,如果您在服務正在前台運行時將其停止,則通知也會被刪除。

如需了解有關通知的詳細信息,請參閱創建狀態欄通知。

管理服務生命周期

服務的生命周期比 Activity 的生命周期要簡單得多。但是,密切關注如何創建和銷毀服務反而更加重要,因為服務可以在用戶沒有意識到的情況下運行於後台。

服務生命周期(從創建到銷毀)可以遵循兩條不同的路徑:

啟動服務

該服務在其他組件調用startService()時創建,然後無限期運行,且必須通過調用stopSelf()來自行停止運行。此外,其他組件也可以通過調用stopService()來停止服務。服務停止後,系統會將其銷毀。

綁定服務

該服務在另一個組件(客戶端)調用bindService()時創建。然後,客戶端通過IBinder接口與服務進行通信。客戶端可以通過調用unbindService()關閉連接。多個客戶端可以綁定到相同服務,而且當所有綁定全部取消後,系統即會銷毀該服務。 (服務不必自行停止運行。)

這兩條路徑並非完全獨立。也就是說,您可以綁定到已經使用startService()啟動的服務。例如,可以通過使用Intent(標識要播放的音樂)調用startService()來啟動後台音樂服務。隨後,可能在用戶需要稍加控制播放器或獲取有關當前播放歌曲的信息時,Activity 可以通過調用bindService()綁定到服務。在這種情況下,除非所有客戶端均取消綁定,否則stopService()或stopSelf()不會真正停止服務。

注意:以上說明提供了音樂播放器的實現思路:使用startService來啟動音樂播放Service,同時使用startForeground()讓服務運行於前台,在狀態欄中顯示通知。然後bindService(),通過onServiceConnected中返回的AIDL接口來控制Service,比如控制播放下一首、上一首以及播放模式等等。然後還可以在返回的AIDL接口中注冊一個回調接口,這樣Service就能實時反饋音樂播放進度給Activity。

實現生命周期回調

與 Activity 類似,服務也擁有生命周期回調方法,您可以實現這些方法來監控服務狀態的變化並適時執行工作。 以下框架服務展示了每種生命周期方法:

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 生命周期回調方法不同,您不需要調用這些回調方法的超類實現。

 

\

 

圖 2.服務生命周期左圖顯示了使用startService()所創建的服務的生命周期,右圖顯示了使用bindService()所創建的服務的生命周期。

通過實現這些方法,您可以監控服務生命周期的兩個嵌套循環:

服務的整個生命周期從調用onCreate()開始起,到onDestroy()返回時結束。與 Activity 類似,服務也在onCreate()中完成初始設置,並在onDestroy()中釋放所有剩余資源。例如,音樂播放服務可以在onCreate()中創建用於播放音樂的線程,然後在onDestroy()中停止該線程。

無論服務是通過startService()還是bindService()創建,都會為所有服務調用onCreate()和onDestroy()方法。

服務的有效生命周期從調用onStartCommand()或onBind()方法開始。每種方法均有Intent對象,該對象分別傳遞到startService()或bindService()。

對於啟動服務,有效生命周期與整個生命周期同時結束(即便是在onStartCommand()返回之後,服務仍然處於活動狀態)。對於綁定服務,有效生命周期在onUnbind()返回時結束。

注:盡管啟動服務是通過調用stopSelf()或stopService()來停止,但是該服務並無相應的回調(沒有onStop()回調)。因此,除非服務綁定到客戶端,否則在服務停止時,系統會將其銷毀—onDestroy()是接收到的唯一回調。

圖 2 說明了服務的典型回調方法。盡管該圖分開介紹通過startService()創建的服務和通過bindService()創建的服務,但是請記住,不管啟動方式如何,任何服務均有可能允許客戶端與其綁定。因此,最初使用onStartCommand()(通過客戶端調用startService())啟動的服務仍可接收對onBind()的調用(當客戶端調用bindService()時)。

如需了解有關創建提供綁定的服務的詳細信息,請參閱綁定服務文檔,該文檔的管理綁定服務的生命周期部分提供了有關onRebind()回調方法的更多信息。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved