Android四大組件——Service

一、定義

Service 是一個(gè)可以在后臺(tái)執(zhí)行長(zhǎng)時(shí)間運(yùn)行操作而不提供用戶(hù)界面的應(yīng)用組件。服務(wù)可由其他應(yīng)用組件啟動(dòng),而且即使用戶(hù)切換到其他應(yīng)用,服務(wù)仍將在后臺(tái)繼續(xù)運(yùn)行。 此外,組件可以綁定到服務(wù),以與之進(jìn)行交互,甚至是執(zhí)行進(jìn)程間通信 (IPC)。

簡(jiǎn)單地說(shuō),服務(wù)是一種即使用戶(hù)未與應(yīng)用交互也可在后臺(tái)運(yùn)行的組件。 因此,您應(yīng)僅在必要時(shí)才創(chuàng)建服務(wù)。

二、場(chǎng)景需求

服務(wù)可以處理網(wǎng)絡(luò)事務(wù)、播放音樂(lè),執(zhí)行文件 I/O 或與內(nèi)容提供程序交互,而所有這一切均可在后臺(tái)進(jìn)行。

如需在主線(xiàn)程外部執(zhí)行工作,不過(guò)只是在用戶(hù)正在與應(yīng)用交互時(shí)才有此需要,則應(yīng)創(chuàng)建新線(xiàn)程而非服務(wù)。 例如,如果您只是想在 Activity 運(yùn)行的同時(shí)播放一些音樂(lè),則可在 onCreate() 中創(chuàng)建線(xiàn)程,在 onStart() 中啟動(dòng)線(xiàn)程,然后在 onStop() 中停止線(xiàn)程。您還可以考慮使用 AsyncTask 或 HandlerThread,而非傳統(tǒng)的 Thread 類(lèi)。

請(qǐng)記住,如果您確實(shí)要使用服務(wù),則默認(rèn)情況下,它仍會(huì)在應(yīng)用的主線(xiàn)程中運(yùn)行,因此,如果服務(wù)執(zhí)行的是密集型或阻止性操作,則您仍應(yīng)在服務(wù)內(nèi)創(chuàng)建新線(xiàn)程。

三、生命周期

服務(wù)的生命周期比 Activity 的生命周期要簡(jiǎn)單得多。但是,密切關(guān)注如何創(chuàng)建和銷(xiāo)毀服務(wù)反而更加重要,因?yàn)榉?wù)可以在用戶(hù)沒(méi)有意識(shí)到的情況下運(yùn)行于后臺(tái)。

服務(wù)生命周期(從創(chuàng)建到銷(xiāo)毀)可以遵循兩條不同的路徑:

啟動(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ì)將其銷(xiāo)毀。

綁定服務(wù)

該服務(wù)在另一個(gè)組件(客戶(hù)端)調(diào)用 bindService() 時(shí)創(chuàng)建。然后,客戶(hù)端通過(guò) IBinder 接口與服務(wù)進(jìn)行通信??蛻?hù)端可以通過(guò)調(diào)用 unbindService() 關(guān)閉連接。多個(gè)客戶(hù)端可以綁定到相同服務(wù),而且當(dāng)所有綁定全部取消后,系統(tǒng)即會(huì)銷(xiāo)毀該服務(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ù)。隨后,可能在用戶(hù)需要稍加控制播放器或獲取有關(guān)當(dāng)前播放歌曲的信息時(shí),Activity 可以通過(guò)調(diào)用 bindService() 綁定到服務(wù)。在這種情況下,除非所有客戶(hù)端均取消綁定,否則 stopService() 或 stopSelf() 不會(huì)實(shí)際停止服務(wù)。

與 Activity 類(lèi)似,服務(wù)也擁有生命周期回調(diào)方法,您可以實(shí)現(xiàn)這些方法來(lái)監(jiān)控服務(wù)狀態(tài)的變化并適時(shí)執(zhí)行工作

服務(wù)生命周期圖

左圖顯示了使用 startService() 所創(chuàng)建的服務(wù)的生命周期,

右圖顯示了使用 bindService() 所創(chuàng)建的服務(wù)的生命周期。

通過(guò)實(shí)現(xiàn)這些方法,您可以監(jiān)控服務(wù)生命周期的兩個(gè)嵌套循環(huán):

服務(wù)的整個(gè)生命周期從調(diào)用 onCreate() 開(kāi)始起,到 onDestroy() 返回時(shí)結(jié)束。與 Activity 類(lèi)似,服務(wù)也在 onCreate() 中完成初始設(shè)置,并在 onDestroy() 中釋放所有剩余資源。例如,音樂(lè)播放服務(wù)可以在 onCreate() 中創(chuàng)建用于播放音樂(lè)的線(xiàn)程,然后在 onDestroy() 中停止該線(xiàn)程。
無(wú)論服務(wù)是通過(guò) startService() 還是 bindService() 創(chuàng)建,都會(huì)為所有服務(wù)調(diào)用 onCreate() 和 onDestroy() 方法。

服務(wù)的有效生命周期從調(diào)用 onStartCommand() 或 onBind() 方法開(kāi)始。每種方法均有 Intent 對(duì)象,該對(duì)象分別傳遞到 startService() 或 bindService()。

對(duì)于啟動(dòng)服務(wù),有效生命周期與整個(gè)生命周期同時(shí)結(jié)束(即便是在 onStartCommand() 返回之后,服務(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ù)綁定到客戶(hù)端,否則在服務(wù)停止時(shí),系統(tǒng)會(huì)將其銷(xiāo)毀 — onDestroy() 是接收到的唯一回調(diào)。

圖 2 說(shuō)明了服務(wù)的典型回調(diào)方法。

盡管該圖分開(kāi)介紹通過(guò) startService() 創(chuàng)建的服務(wù)和通過(guò) bindService() 創(chuàng)建的服務(wù),但是請(qǐng)記住,不管啟動(dòng)方式如何,任何服務(wù)均有可能允許客戶(hù)端與其綁定。因此,最初使用 onStartCommand()(通過(guò)客戶(hù)端調(diào)用 startService())啟動(dòng)的服務(wù)仍可接收對(duì) onBind() 的調(diào)用(當(dāng)客戶(hù)端調(diào)用 bindService() 時(shí))。

以下框架服務(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
    }
}
生命周期方法具體介紹

主要介紹內(nèi)部調(diào)用方法 & 外部調(diào)用方法的關(guān)系。

示意圖
常見(jiàn)的生命周期使用
示意圖

三、服務(wù)創(chuàng)建的兩種方式

1.創(chuàng)建啟動(dòng)服務(wù)(startService)

啟動(dòng)服務(wù)由另一個(gè)組件通過(guò)調(diào)用 startService() 啟動(dòng),這會(huì)導(dǎo)致調(diào)用服務(wù)的 onStartCommand() 方法。

服務(wù)啟動(dòng)之后,其生命周期即獨(dú)立于啟動(dòng)它的組件,并且可以在后臺(tái)無(wú)限期地運(yùn)行,即使啟動(dòng)服務(wù)的組件已被銷(xiāo)毀也不受影響。 因此,服務(wù)應(yīng)通過(guò)調(diào)用 stopSelf() 結(jié)束工作來(lái)自行停止運(yùn)行,或者由另一個(gè)組件通過(guò)調(diào)用 stopService() 來(lái)停止它。

應(yīng)用組件(如 Activity)可以通過(guò)調(diào)用 startService() 方法并傳遞 Intent 對(duì)象(指定服務(wù)并包含待使用服務(wù)的所有數(shù)據(jù))來(lái)啟動(dòng)服務(wù)。服務(wù)通過(guò) onStartCommand() 方法接收此 Intent。

例如,假設(shè)某 Activity 需要將一些數(shù)據(jù)保存到在線(xiàn)數(shù)據(jù)庫(kù)中。該 Activity 可以啟動(dòng)一個(gè)協(xié)同服務(wù),并通過(guò)向 startService() 傳遞一個(gè) Intent,為該服務(wù)提供要保存的數(shù)據(jù)。服務(wù)通過(guò) onStartCommand() 接收 Intent,連接到互聯(lián)網(wǎng)并執(zhí)行數(shù)據(jù)庫(kù)事務(wù)。事務(wù)完成之后,服務(wù)會(huì)自行停止運(yùn)行并隨即被銷(xiāo)毀。

注意:默認(rèn)情況下,服務(wù)與服務(wù)聲明所在的應(yīng)用運(yùn)行于同一進(jìn)程,而且運(yùn)行于該應(yīng)用的主線(xiàn)程中。 因此,如果服務(wù)在用戶(hù)與來(lái)自同一應(yīng)用的 Activity 進(jìn)行交互時(shí)執(zhí)行密集型或阻止性操作,則會(huì)降低 Activity 性能。 為了避免影響應(yīng)用性能,您應(yīng)在服務(wù)內(nèi)啟動(dòng)新線(xiàn)程。

從傳統(tǒng)上講,您可以擴(kuò)展兩個(gè)類(lèi)來(lái)創(chuàng)建啟動(dòng)服務(wù):

Service

這是適用于所有服務(wù)的基類(lèi)。擴(kuò)展此類(lèi)時(shí),必須創(chuàng)建一個(gè)用于執(zhí)行所有服務(wù)工作的新線(xiàn)程,因?yàn)槟J(rèn)情況下,服務(wù)將使用應(yīng)用的主線(xiàn)程,這會(huì)降低應(yīng)用正在運(yùn)行的所有 Activity 的性能。

IntentService

這是 Service 的子類(lèi),它使用工作線(xiàn)程逐一處理所有啟動(dòng)請(qǐng)求。如果您不要求服務(wù)同時(shí)處理多個(gè)請(qǐng)求,這是最好的選擇。 您只需實(shí)現(xiàn) onHandleIntent() 方法即可,該方法會(huì)接收每個(gè)啟動(dòng)請(qǐng)求的 Intent,使您能夠執(zhí)行后臺(tái)工作。

2.創(chuàng)建綁定服務(wù)(bindService)

綁定服務(wù)允許應(yīng)用組件通過(guò)調(diào)用 bindService() 與其綁定,以便創(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() 來(lái)檢索該接口,并開(kāi)始對(duì)服務(wù)調(diào)用方法。服務(wù)只用于與其綁定的應(yīng)用組件,因此如果沒(méi)有組件綁定到服務(wù),則系統(tǒng)會(huì)銷(xiāo)毀服務(wù)(您不必按通過(guò) onStartCommand() 啟動(dòng)的服務(wù)那樣來(lái)停止綁定服務(wù))。

要?jiǎng)?chuàng)建綁定服務(wù),首先必須定義指定客戶(hù)端如何與服務(wù)通信的接口。 服務(wù)與客戶(hù)端之間的這個(gè)接口必須是 IBinder 的實(shí)現(xiàn),并且服務(wù)必須從 onBind() 回調(diào)方法返回它。一旦客戶(hù)端收到 IBinder,即可開(kāi)始通過(guò)該接口與服務(wù)進(jìn)行交互。

多個(gè)客戶(hù)端可以同時(shí)綁定到服務(wù)??蛻?hù)端完成與服務(wù)的交互后,會(huì)調(diào)用 unbindService() 取消綁定。一旦沒(méi)有客戶(hù)端綁定到該服務(wù),系統(tǒng)就會(huì)銷(xiāo)毀它。

四、在前臺(tái)運(yùn)行服務(wù)

前臺(tái)服務(wù)被認(rèn)為是用戶(hù)主動(dòng)意識(shí)到的一種服務(wù),因此在內(nèi)存不足時(shí),系統(tǒng)也不會(huì)考慮將其終止。 前臺(tái)服務(wù)必須為狀態(tài)欄提供通知,放在“正在進(jìn)行”標(biāo)題下方,這意味著除非服務(wù)停止或從前臺(tái)移除,否則不能清除通知。

例如,應(yīng)該將通過(guò)服務(wù)播放音樂(lè)的音樂(lè)播放器設(shè)置為在前臺(tái)運(yùn)行,這是因?yàn)橛脩?hù)明確意識(shí)到其操作。 狀態(tài)欄中的通知可能表示正在播放的歌曲,并允許用戶(hù)啟動(dòng) Activity 來(lái)與音樂(lè)播放器進(jìn)行交互。

要請(qǐng)求讓服務(wù)運(yùn)行于前臺(tái),請(qǐng)調(diào)用 startForeground()。此方法采用兩個(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() 的整型 ID 不得為 0。

要從前臺(tái)移除服務(wù),請(qǐng)調(diào)用 stopForeground()。此方法采用一個(gè)布爾值,指示是否也移除狀態(tài)欄通知。 此方法不會(huì)停止服務(wù)。 但是,如果您在服務(wù)正在前臺(tái)運(yùn)行時(shí)將其停止,則通知也會(huì)被移除。

五、IntentService

這是 Service 的子類(lèi),它使用工作線(xiàn)程逐一處理所有啟動(dòng)請(qǐng)求。如果您不要求服務(wù)同時(shí)處理多個(gè)請(qǐng)求,這是最好的選擇。 您只需實(shí)現(xiàn) onHandleIntent() 方法即可,該方法會(huì)接收每個(gè)啟動(dòng)請(qǐng)求的 Intent,使您能夠執(zhí)行后臺(tái)工作。

由于大多數(shù)啟動(dòng)服務(wù)都不必同時(shí)處理多個(gè)請(qǐng)求(實(shí)際上,這種多線(xiàn)程情況可能很危險(xiǎn)),因此使用 IntentService 類(lèi)實(shí)現(xiàn)服務(wù)也許是最好的選擇。

IntentService 執(zhí)行以下操作:

創(chuàng)建默認(rèn)的工作線(xiàn)程,用于在應(yīng)用的主線(xiàn)程外執(zhí)行傳遞給 onStartCommand() 的所有 Intent。

創(chuàng)建工作隊(duì)列,用于將 Intent 逐一傳遞給 onHandleIntent()實(shí)現(xiàn),這樣您就永遠(yuǎn)不必?fù)?dān)心多線(xiàn)程問(wèn)題。在處理完所有啟動(dòng)請(qǐng)求后停止服務(wù),因此您永遠(yuǎn)不必調(diào)用 stopSelf()。提供 onBind() 的默認(rèn)實(shí)現(xiàn)(返回 null)。提供 onStartCommand() 的默認(rèn)實(shí)現(xiàn),可將 Intent 依次發(fā)送到工作隊(duì)列和 onHandleIntent() 實(shí)現(xiàn)。

綜上所述,您只需實(shí)現(xiàn) onHandleIntent() 來(lái)完成客戶(hù)端提供的工作即可。(不過(guò),您還需要為服務(wù)提供小型構(gòu)造函數(shù)。)

以下是 IntentService 的實(shí)現(xiàn)示例:

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.
      try {
          Thread.sleep(5000);
      } catch (InterruptedException e) {
          // Restore interrupt status.
          Thread.currentThread().interrupt();
      }
  }
}

六、創(chuàng)建服務(wù)

您必須創(chuàng)建 Service 的子類(lèi)(或使用它的一個(gè)現(xiàn)有子類(lèi))。在實(shí)現(xiàn)中,您需要重寫(xiě)一些回調(diào)方法,以處理服務(wù)生命周期的某些關(guān)鍵方面并提供一種機(jī)制將組件綁定到服務(wù)(如適用)。 應(yīng)重寫(xiě)的最重要的回調(diào)方法包括:

onStartCommand()
當(dāng)另一個(gè)組件(如 Activity)通過(guò)調(diào)用 startService() 請(qǐng)求啟動(dòng)服務(wù)時(shí),系統(tǒng)將調(diào)用此方法。一旦執(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)此方法。)
onBind()
當(dāng)另一個(gè)組件想通過(guò)調(diào)用 bindService() 與服務(wù)綁定(例如執(zhí)行 RPC)時(shí),系統(tǒng)將調(diào)用此方法。在此方法的實(shí)現(xiàn)中,您必須通過(guò)返回 IBinder 提供一個(gè)接口,供客戶(hù)端用來(lái)與服務(wù)進(jìn)行通信。請(qǐng)務(wù)必實(shí)現(xiàn)此方法,但如果您并不希望允許綁定,則應(yīng)返回 null。
onCreate()
首次創(chuàng)建服務(wù)時(shí),系統(tǒng)將調(diào)用此方法來(lái)執(zhí)行一次性設(shè)置程序(在調(diào)用 onStartCommand() 或 onBind() 之前)。如果服務(wù)已在運(yùn)行,則不會(huì)調(diào)用此方法。
onDestroy()
當(dāng)服務(wù)不再使用且將被銷(xiāo)毀時(shí),系統(tǒng)將調(diào)用此方法。服務(wù)應(yīng)該實(shí)現(xiàn)此方法來(lái)清理所有資源,如線(xiàn)程、注冊(cè)的偵聽(tīng)器、接收器等。 這是服務(wù)接收的最后一個(gè)調(diào)用。

如果組件通過(guò)調(diào)用 startService() 啟動(dòng)服務(wù)(這會(huì)導(dǎo)致對(duì) onStartCommand() 的調(diào)用),則服務(wù)將一直運(yùn)行,直到服務(wù)使用 stopSelf() 自行停止運(yùn)行,或由其他組件通過(guò)調(diào)用 stopService() 停止它為止。

如果組件是通過(guò)調(diào)用 bindService() 來(lái)創(chuàng)建服務(wù)(且未調(diào)用 onStartCommand(),則服務(wù)只會(huì)在該組件與其綁定時(shí)運(yùn)行。一旦該服務(wù)與所有客戶(hù)端之間的綁定全部取消,系統(tǒng)便會(huì)銷(xiāo)毀它。

僅當(dāng)內(nèi)存過(guò)低且必須回收系統(tǒng)資源以供具有用戶(hù)焦點(diǎn)的 Activity 使用時(shí),Android 系統(tǒng)才會(huì)強(qiáng)制停止服務(wù)。如果將服務(wù)綁定到具有用戶(hù)焦點(diǎn)的 Activity,則它不太可能會(huì)終止;如果將服務(wù)聲明為在前臺(tái)運(yùn)行(稍后討論),則它幾乎永遠(yuǎn)不會(huì)終止。或者,如果服務(wù)已啟動(dòng)并要長(zhǎng)時(shí)間運(yùn)行,則系統(tǒng)會(huì)隨著時(shí)間的推移降低服務(wù)在后臺(tái)任務(wù)列表中的位置,而服務(wù)也將隨之變得非常容易被終止;如果服務(wù)是啟動(dòng)服務(wù),則您必須將其設(shè)計(jì)為能夠妥善處理系統(tǒng)對(duì)它的重啟。 如果系統(tǒng)終止服務(wù),那么一旦資源變得再次可用,系統(tǒng)便會(huì)重啟服務(wù)。

七、使用清單文件聲明服務(wù)

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

要聲明服務(wù),請(qǐng)?zhí)砑?<service> 元素作為
<application> 元素的子元素。例如:

<manifest ... >
  ...
  <application ... >
      <service android:name=".ExampleService" />
      ...
  </application>
</manifest>

您還可將其他屬性包括在 <service> 元素中,以定義一些特性,如啟動(dòng)服務(wù)及其運(yùn)行所在進(jìn)程所需的權(quán)限。android:name 屬性是唯一必需的屬性,用于指定服務(wù)的類(lèi)名。應(yīng)用一旦發(fā)布,即不應(yīng)更改此類(lèi)名,如若不然,可能會(huì)存在因依賴(lài)顯式 Intent 啟動(dòng)或綁定服務(wù)而破壞代碼的風(fēng)險(xiǎn)。

為了確保應(yīng)用的安全性,請(qǐng)始終使用顯式 Intent 啟動(dòng)或綁定 Service,且不要為服務(wù)聲明 Intent 過(guò)濾器。 啟動(dòng)哪個(gè)服務(wù)存在一定的不確定性,而如果對(duì)這種不確定性的考量非常有必要,則可為服務(wù)提供 Intent 過(guò)濾器并從 Intent 中排除相應(yīng)的組件名稱(chēng),但隨后必須使用 setPackage() 方法設(shè)置 Intent 的軟件包,這樣可以充分消除目標(biāo)服務(wù)的不確定性。

此外,還可以通過(guò)添加 android:exported 屬性并將其設(shè)置為 "false",確保服務(wù)僅適用于您的應(yīng)用。這可以有效阻止其他應(yīng)用啟動(dòng)您的服務(wù),即便在使用顯式 Intent 時(shí)也如此。

八、onStartCommand()的返回值

onStartCommand() 方法必須返回整型數(shù)。整型數(shù)是一個(gè)值,用于描述系統(tǒng)應(yīng)該如何在服務(wù)終止的情況下繼續(xù)運(yùn)行服務(wù)(如上所述,IntentService 的默認(rèn)實(shí)現(xiàn)將為您處理這種情況,不過(guò)您可以對(duì)其進(jìn)行修改)。從 onStartCommand() 返回的值必須是以下常量之一:

START_NOT_STICKY</p>
如果系統(tǒng)在 onStartCommand() 返回后終止服務(wù),則除非有掛起 Intent 要傳遞,否則系統(tǒng)不會(huì)重建服務(wù)。這是最安全的選項(xiàng),可以避免在不必要時(shí)以及應(yīng)用能夠輕松重啟所有未完成的作業(yè)時(shí)運(yùn)行服務(wù)。 </p>
START_STICKY</p>
如果系統(tǒng)在 onStartCommand() 返回后終止服務(wù),則會(huì)重建服務(wù)并調(diào)用 onStartCommand(),但不會(huì)重新傳遞最后一個(gè) Intent。相反,除非有掛起 Intent 要啟動(dòng)服務(wù)(在這種情況下,將傳遞這些 Intent ),否則系統(tǒng)會(huì)通過(guò)空 Intent 調(diào)用 onStartCommand()。這適用于不執(zhí)行命令、但無(wú)限期運(yùn)行并等待作業(yè)的媒體播放器(或類(lèi)似服務(wù))。</p>
START_REDELIVER_INTENT</p>
如果系統(tǒng)在 onStartCommand() 返回后終止服務(wù),則會(huì)重建服務(wù),并通過(guò)傳遞給服務(wù)的最后一個(gè) Intent 調(diào)用 onStartCommand()。任何掛起 Intent 均依次傳遞。這適用于主動(dòng)執(zhí)行應(yīng)該立即恢復(fù)的作業(yè)(例如下載文件)的服務(wù)。

寫(xiě)在最后: 本系列的文章旨在學(xué)習(xí)過(guò)程中的總結(jié),如果對(duì)你也有幫助,榮幸之至。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 啟動(dòng)Service分為兩種方式,分別是start方式和bind方式。 start方式對(duì)應(yīng)的是Service由Con...
    sososeen09閱讀 2,076評(píng)論 0 0
  • 服務(wù)基本上分為兩種形式 啟動(dòng) 當(dāng)應(yīng)用組件(如 Activity)通過(guò)調(diào)用 startService() 啟動(dòng)服務(wù)時(shí)...
    pifoo閱讀 1,331評(píng)論 0 8
  • Service是可以長(zhǎng)時(shí)間運(yùn)行在后臺(tái)的沒(méi)有用戶(hù)界面的組件(區(qū)別于A(yíng)ctivity),運(yùn)行與UI線(xiàn)程中(區(qū)別與Thr...
    Samuel_Tom閱讀 227評(píng)論 0 0
  • [文章內(nèi)容來(lái)自Developers] Service是一個(gè)可以在后臺(tái)執(zhí)行長(zhǎng)時(shí)間運(yùn)行操作而不提供用戶(hù)界面的應(yīng)用組件。...
    岳小川閱讀 938評(píng)論 0 7
  • (一) 海妖的宮殿坐落在海底柔軟的白沙上,用最無(wú)暇的白珊瑚與最嬌艷的紅珊瑚砌成。淡紫色,粉紅色與金綠色的海葵輕輕搖...
    四海為家的兔子閱讀 1,137評(píng)論 3 9

友情鏈接更多精彩內(nèi)容