Service不徹底解析

本篇的內容並非介紹service使用方法和生命週期的,而是對其中的一些要點進行記錄和分析。html

        咱們都知道,Service是一個在後臺執行的應用組件,用於在後臺進行長期操做,例如進行網絡事務,播放背景音樂等等。它又兩種啓動方式,若是其餘的應用組件但願與該service進程內通訊(IPC),能夠經過與該service綁定來實現。關於生命週期的問題就不囉嗦了,直接放官檔的圖:android

image

        不管何種方式啓動service,任何應用組件均可以使用該service。若是但願只有你本身的app才能使用該service,那麼須要在manifest文件中加入android:exported屬性,並將其設置爲false。Android官方建議咱們儘可能使用顯式的方式來啓動service,從而保證app的安全。安全

        另外,咱們須要注意的是,在默認狀況下service並不會從新開啓一個獨立的線程運行,而是運行於宿主進程的主線程中。顯然,若是咱們須要進行耗時操做,例如上面提到的播放背景音樂,網絡操做等等,該如何解決?網絡

    • 咱們能夠在activity中建立新線程,並在activity中對線程進行建立啓動和銷燬;
    • 使用asyncTask來完成任務;
    • 在service中新開一個線程來完成這些任務,以防ANR錯誤。

IntentService       多線程

        當咱們不須要同時處理多個請求的狀況下,咱們最好的解決方案是使用IntentService完成任務,而咱們只需重寫onHandleIntent()來完成處理邏輯便可。在IntentService進行了如下工做:併發

    • 新啓動了一個worker線程來執行那些提交給onStartComand方法的intent任務。
    • 建立了一個work隊列來存放多個請求任務,每次只向onHandleIntent()方法來傳遞一個intent來處理。
    • 當全部請求任務都完成後,則自動中止該service。
    • 默認的onStartCommand()方法中,將收到的intent參數傳遞給onHandleIntent()來處理。

        下面是一個IntentService的示例:app

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) {
              }
          }
      }
  }
}

        這裏只需實現一個簡單的構造函數和intent處理方法就能夠了。固然,咱們也能夠根據須要重寫service生命週期中的其餘方法,可是請記得調用父類方法。咱們須要清楚的是,全部提交給該service的任務都以intent的形式存放於一個隊列中,IntentService裏惟一的worker線程每次取一個intent來處理,都處理完後自動關閉IntentService。async

        若是但願多線程併發處理任務,那麼須要繼承service來處理任務了。這裏就不演示具體代碼了,可是有一點須要提醒一下。在onStartCommand方法會返回一個int值,一般咱們返回父類的方法,這裏的int值描述了當系統幹掉service後的操做,它的幾個常量選項以下:ide

    • START_NOT_STICKY當onStartCommand方法返回後,系統殺死了service,除非又有intent請求傳遞進來,不然將不會從新啓動service。該選項能夠很安全地確保當應用程序重啓那些未完成的工做,而並不須要運行service時,避免service的啓動運行。
    • START_STICKY當onStartCommand方法返回後,系統殺死了service,那麼將會從新啓動service,並執行onStartCommand方法,可是從新傳遞進來的intent並非上一個intent了,而是使用null來代替(除非有新的intent請求)。該選項適用於相似於媒體播放器這種service,不執行任何命令,只是一直在運行等待任務。
    • START_REDELIVER_INTENT當onStartCommand方法返回後,系統殺死了service,那麼將會從新啓動service,並執行onStartCommand方法,從新傳遞進來的intent與上一個相同,隨後而來的intent請求將會依次執行。該選項適用於相似下載任務的service,一直處於活躍狀態,一旦掛掉就須要當即恢復。

        另外,service還經常與notification相結合使用,使service能夠運行到前臺,例如音樂播聽任務等等,能夠與用戶交互,這些內容之後再介紹。函數

相關文章
相關標籤/搜索