Android Service的生命週期

  service的生命週期,從它被建立開始,到它被銷燬爲止,能夠有兩條不一樣的路徑:html

A started service

  被開啓的service經過其餘組件調用 startService()被建立。java

  這種service能夠無限地運行下去,必須調用stopSelf()方法或者其餘組件調用stopService()方法來中止它。android

  當service被中止時,系統會銷燬它。git

 

A bound service

  被綁定的service是當其餘組件(一個客戶)調用bindService()來建立的。github

  客戶能夠經過一個IBinder接口和service進行通訊。app

  客戶能夠經過 unbindService()方法來關閉這種鏈接。ide

  一個service能夠同時和多個客戶綁定,當多個客戶都解除綁定以後,系統會銷燬service。函數

 

  這兩條路徑並非徹底分開的。oop

  便是說,你能夠和一個已經調用了 startService()而被開啓的service進行綁定。ui

  好比,一個後臺音樂service可能因調用 startService()方法而被開啓了,稍後,可能用戶想要控制播放器或者獲得一些當前歌曲的信息,能夠經過bindService()將一個activity和service綁定。這種狀況下,stopService()或 stopSelf()實際上並不能中止這個service,除非全部的客戶都解除綁定。

 

Implementing the lifecycle callbacks

  和activity同樣,service也有一系列的生命週期回調函數,你能夠實現它們來監測service狀態的變化,而且在適當的時候執行適當的工做。

  下面的service展現了每個生命週期的方法:

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的生命週期回調函數,你不須要調用基類的實現。

 

  這個圖說明了service典型的回調方法,儘管這個圖中將開啓的service和綁定的service分開,可是你須要記住,任何service都潛在地容許綁定。

  因此,一個被開啓的service仍然可能被綁定。

  實現這些方法,你能夠看到兩層嵌套的service的生命週期:

 

The entire lifetime

  service總體的生命時間是從onCreate()被調用開始,到onDestroy()方法返回爲止。

  和activity同樣,service在onCreate()中進行它的初始化工做,在onDestroy()中釋放殘留的資源。

  好比,一個音樂播放service能夠在onCreate()中建立播放音樂的線程,在onDestory()中中止這個線程。

   onCreate() 和 onDestroy()會被全部的service調用,不論service是經過startService()仍是bindService()創建。

 

The active lifetime

  service積極活動的生命時間(active lifetime)是從onStartCommand() onBind()被調用開始,它們各自處理由startService()或 bindService()方法傳過來的Intent對象。

  若是service是被開啓的,那麼它的活動生命週期和整個生命週期一同結束。

  若是service是被綁定的,它們它的活動生命週期是在onUnbind()方法返回後結束。

  注意:儘管一個被開啓的service是經過調用 stopSelf() 或 stopService()來中止的,沒有一個對應的回調函數與之對應,即沒有onStop()回調方法。因此,當調用了中止的方法,除非這個service和客戶組件綁定,不然系統將會直接銷燬它,onDestory()方法會被調用,而且是這個時候惟一會被調用的回調方法。

 

Managing the Lifecycle of 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(被開啓,還容許綁定)的生命週期:

 

注意點:

    運行後,產生了以下所示的bug:

    04-27 12:09:49.033 718-718/com.haier.oet.androidplayerground E/AndroidRuntime: FATAL EXCEPTION: main     Process: com.haier.oet.androidplayerground, PID: 718     java.lang.IllegalStateException: Could not execute method of the activity         at android.view.View$1.onClick(View.java:4221)         at android.view.View.performClick(View.java:5155)         at android.view.View$PerformClick.run(View.java:20747)         at android.os.Handler.handleCallback(Handler.java:739)         at android.os.Handler.dispatchMessage(Handler.java:95)         at android.os.Looper.loop(Looper.java:145)         at android.app.ActivityThread.main(ActivityThread.java:5835)         at java.lang.reflect.Method.invoke(Native Method)         at java.lang.reflect.Method.invoke(Method.java:372)         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)  

問題緣由:

有些時候咱們使用Service的時須要採用隱式意圖啓動的方式,可是Android 5.0一出來後,其中有個特性就是Service Intent  must be explitict,也就是說從Lollipop開始,Service服務必須採用顯式意圖方式啓動。

解決方法:

Intent intent = new Intent();
intent.setAction(ServiceDemo.ACTION);
intent.setPackage("com.example.servicedemoactivity");
bindService(intent, conn, BIND_AUTO_CREATE);

 

實例代碼地址:

    https://github.com/wangzhiyuan888/ServiceDemoActivity

 

參考資料

  API Guides:Services

  http://developer.android.com/guide/components/services.html

  API Guides:Bound Services

  http://developer.android.com/guide/components/bound-services.html

相關文章
相關標籤/搜索