1. 程式人生 > >Android開發四大元件之Service(詳解篇)

Android開發四大元件之Service(詳解篇)

Android開發之四大元件——Service

一、Service

簡介

Service是android系統中的四大元件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的級別差不多,區別是Service只能執行在後臺不提供使用者介面,並且可以和其他元件進行互動。一個Service是一個可以長期執行在後臺的應用程式元件,不提供使用者介面。 另一個應用程式元件可以啟動一個服務,它將繼續在後臺執行,即使 使用者切換到另一個應用程式。 此外,一個元件可以繫結到一個服務 與之互動,甚至執行程序間通訊(IPC)。 例如,一個服務可以在後臺處理網路交易、播放音樂、執行檔案I / O,或與內容提供者互動等。

一個服務可以基本上有兩種形式:

Started:

一個服務將被開啟,當一個應用程式元件(例如,一個Activity)啟動它 呼叫startService()。一個服務一旦啟動,可以無限期地在後臺執行,即使啟動它的元件被摧毀。通常情況下, 開始服務執行一個操作,不向呼叫者返回一個結果。 例如,它可能通過網路下載或上傳檔案。 當操作完成, 服務應該自動銷燬。

Bound

一個服務被“繫結”當一個應用程式元件繫結到它通過呼叫bindService()。一個繫結服務提供了一個客戶端 - 伺服器介面,允許元件與服務互動,傳送請求,得到的結果,甚至這樣做跨程序與程序間通訊(IPC)。一個service可以同時和多個客戶繫結,當多個客戶都解除繫結之後,系統會銷燬service

注意:一個服務執行在其宿主程序,該服務不會建立自己的執行緒,並不在一個單獨的程序中執行的主執行緒(除非另行指定)。這意味著,如果你的服務是打算進行任何耗時操作(例如MP3播放或網路下載等),你應該在該服務中建立一個新的執行緒來執行該工作。通過使用一個單獨的執行緒,你會減少應用程式的不響應(ANR)錯誤和應用程式的UI主執行緒可以繼續致力於為響應使用者的操作。

二、建立Service

要建立一個服務,你必須建立Service的子類(或者其現有的一個子類)。在實現的子類中處理Service生命週期的關鍵方面的一些回撥方法,並提供了一種機制,元件繫結到該服務,可以根據需要重寫這些回撥方法:

onStartCommand()

每次客戶端呼叫startService()方法啟動該Service都會回撥該方法。

onBind()

該方法是每個Service的子類必須實現的方法。該方法返回一個IBinder物件,應用程式可以通過該物件和Service元件進行通訊。如果你不希望允許繫結,那麼應該返回null。

onCreate()

當Service第一次被建立後將立即回撥該方法。

onDestroy()

當Service被銷燬之前回調該方法,你建立的Service應該在這個方法中清理不在使用的資源,如執行緒,註冊的偵聽器,接收器等。

在配置檔案中註冊Service:

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

三、IntentService

因為開始的服務不需要同時處理多個請求(實際上是一個危險的多執行緒的情況下)這可能是最好的如果你實現你的服務使用intentservice

 IntentService是Service類的子類,用來處理非同步請求。客戶端可以通過startService(Intent)方法傳遞請求給IntentService。IntentService在onCreate()函式中通過HandlerThread單獨開啟一個執行緒來處理所有Intent請求物件(通過startService的方式傳送過來的)所對應的任務,這樣以免事務處理阻塞主執行緒。執行完所一個Intent請求物件所對應的工作之後,如果沒有新的Intent請求達到,則自動停止Service;否則執行下一個Intent請求所對應的任務。

IntentService在處理事務時,還是採用的Handler方式,建立一個名叫ServiceHandler的內部Handler,並把它直接繫結到HandlerThread所對應的子執行緒。 ServiceHandler把處理一個intent所對應的事務都封裝到叫做onHandleIntent的虛擬函式;因此我們直接實現虛擬函式onHandleIntent,再在裡面根據Intent的不同進行不同的事務處理就可以了。

另外,IntentService預設實現了Onbind()方法,返回值為null。

  使用IntentService需要兩個步驟:

  1、寫建構函式

  2、實現虛擬函式onHandleIntent,並在裡面根據Intent的不同進行不同的事務處理就可以了。

好處:處理非同步請求的時候可以減少寫程式碼的工作量,比較輕鬆地實現專案的需求

注意:IntentService的建構函式一定是引數為空的建構函式,然後再在其中呼叫super("name")這種形式的建構函式。

因為Service的例項化是系統來完成的,而且系統是用引數為空的建構函式來例項化Service的

下面是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 workerthread 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){
              }
          }
      }
  }
}

四、The Lifecycle of a Service

不像是activity的生命週期回撥函式,你不需要呼叫父類執行這些回撥方法。


注:左邊的圖顯示了使用的StartService()建立的服務的生命週期和右邊的圖顯示了使用StartService()建立的服務的生命週期。

·        Service整體的生命時間是從onCreate()呼叫開始,到onDestroy()方法返回為止。和Activity一樣,Service在onCreate()中進行它的初始化工作,在onDestroy()中釋放殘留的資源。比如,一個音樂播放Service可以在onCreate()中建立播放音樂的執行緒,在onDestory()中停止這個執行緒。  onCreate() 和 onDestroy()會被所有的Service呼叫,不論Service是通過startService()還是bindService()建立。

·        Service積極活動的生命時間(activelifetime)是從onStartCommand() 或onBind()被呼叫開始,它們各自處理由startService()或 bindService()方法傳過來的Intent物件。

  如果Service是通過startService()開啟的,那麼它的活動生命週期和整個生命週期一同結束。

  如果Service是通過bindService ()開啟的,它們它的活動生命週期是在onUnbind()方法返回後結束。

  注意:儘管一個被開啟的Service是通過呼叫 stopSelf() 或 stopService()來停止的,沒有一個對應的回撥函式與之對應,即沒有onStop()回撥方法。所以,當呼叫了停止的方法,除非這個Service和客戶元件繫結,否則系統將會直接銷燬它,onDestory()方法會被呼叫,並且是這個時候唯一會被呼叫的回撥方法。

五、Managing the Lifecycleof a Bound Service

當繫結Service和所有客戶端解除繫結之後,Android系統將會銷燬它,(除非它同時被onStartCommand()方法開啟)。

因此,如果你的Service是一個純粹的繫結Service,那麼你不需要管理它的生命週期。

然而,如果你選擇實現onStartCommand()回撥方法,那麼你必須顯式地停止service,因為service此時被看做是開啟的。

這種情況下,Service會一直執行到它自己呼叫 stopSelf()或另一個元件呼叫stopService(),不論它是否和客戶端繫結。

另外,如果你的Service被開啟並且接受繫結,那麼當系統呼叫你的 onUnbind()方法時,如果你想要在下次客戶端繫結的時候接受一個onRebind()的呼叫(而不是呼叫 onBind()),你可以選擇在 onUnbind()中返回true。onRebind()的返回值為void,但是客戶端仍然在它的 onServiceConnected()回撥方法中得到 IBinder 物件。

下圖展示了這種Service(被開啟,還允許繫結)的生命週期:


未完待續.............