1. 程式人生 > >Android Service詳解

Android Service詳解

各位肯定知道 Service 作為 Android 的四大元件之一是非常重要的。不過說實話,我實際開發專案中服務用的並不多,(可能和需求有關吧)但是筆試的時候,幾乎是必出的題目了,所以我們今天就來仔細的回顧一下 Service 。

1. 什麼是服務?

Service 是表示應用程式需求的應用程式元件,在不與使用者互動的情況下執行長時間執行的操作,或者給其他應用程式提供使用的功能。Service 是和應用程式在同一個程序中執行的,Service 並不是一個執行緒,所以它並不是用來處理耗時操作的。

2. 啟動服務的方式有幾種?(啟動服務需要在 AndroidManifest.xml 檔案配置)

  • Context.startService()
  • Context.bindService()
  • 先 Context.startService() 在 Context.bindService()

3. Service 的方法和常量有哪些?

Return Methode
final Application

getApplication()

返回擁有此服務的Application。

adstract IBinder

onBind(Intent intent)

將通訊通道返回給服務。

void

onConfigurationChanged(Configuration newConfig)

當元件執行時,裝置配置發生變化時由系統呼叫。

void

onCreate()

首次建立服務時由系統呼叫。

void

onDestroy()

由系統呼叫以通知服務它已不再使用且正在被刪除。

void

onLowMemory()

當整個系統記憶體不足時呼叫此方法,並且主動執行的程序應調整其記憶體使用量。

void

onRebind()

當新客戶端連線到服務時呼叫,在此之前,它已經被通知所有客戶端在其onUnbind(Intent)中斷開連線。

void

onStart(Intent intent,int startId)

此方法在API級別5中已棄用。請實現onStartCommand(Intent,int,int)。

int

onStartCommand(Intent intent,int flags,int startId)

每次客戶端通過呼叫Context.startService(Intent)顯式啟動服務時,由系統呼叫,提供它提供的引數和表示啟動請求的唯一整數標記。

void

onTaskRemoved(Intent rootIntent)

如果服務當前正在執行,且使用者刪除了來自服務應用程式的任務,則呼叫此函式。

void

onTrimMemory(int level)

當作業系統確定是程序從程序中刪除不需要的記憶體的好時機時呼叫。

boolean

onUnbind(Intent intent)

當所有客戶端與服務釋出的特定介面斷開連線時呼叫。

final void

startForeground(int flags)

將此服務從前臺狀態刪除,允許在需要更多記憶體時終止該服務。

final void

startForeground(boolean removeNotification)

同 startForeground(int flags)

final void

startForeground(int id,Notification notification)

如果您的服務已啟動(通過Context.startService(Intent)執行),則還要使此服務在前臺執行,從而提供在此狀態下向使用者顯示的持續通知。

final void

stopSelf()

停止服務,如果服務之前已經啟動。

final void

stopSelf(int startId)

不再返回結果的舊版本的stopSelfResult(int)。

final boolean

stopSelfResult(int startId)

如果最近一次啟動的是startId,則停止服務。

Constants
int

START_CONTINUATION_MASK

onStartCommand返回的位(Intent, int, int)描述瞭如果服務被終止,如何繼續服務。

int

START_FLAG_REDELIVERY

如果Intent是先前傳遞的intent的重新傳遞,則此標誌在onStartCommand(Intent,int,int)中設定,因為該服務先前已返回START_REDELIVER_INTENT但在為該Intent呼叫stopSelf(int)之前已被殺死。

int

START_FLAG_RETRY

如果意圖是重試,則在onStartCommand(Intent, int, int)中設定此標誌,因為初始嘗試從未到達或從onStartCommand(Intent, int, int)返回。

int

START_NOT_STICKY

從onStartCommand(Intent,int,int)返回的常量:如果此服務的程序在啟動時被終止(從onStartCommand(Intent,int,int)返回後),並且沒有新的啟動意圖要傳遞給它,那麼 將服務從啟動狀態中取出,並且在將來顯式呼叫Context.startService(Intent)之前不要重新建立。

int

START_REDELIVER_INTENT

從onStartCommand(Intent,int,int)返回的常量:如果此服務的程序在啟動時被終止(從onStartCommand(Intent,int,int)返回後),則它將被安排重新啟動並且最後一次傳遞的Intent 通過onStartCommand(Intent,int,int)再次傳遞給它。

int

START_STICKY

從onStartCommand(Intent,int,int)返回的常量:如果此服務的程序在啟動時被終止(從onStartCommand(Intent,int,int)返回後),則將其保留在啟動狀態但不保留此狀態 交付 intent。

int

START_STICKY_COMPATIBILITY

從onStartCommand(Intent,int,int)返回的常量:START_STICKY的相容版本,不保證在被殺死後再次呼叫onStartCommand(Intent,int,int)。

int

STOP_FOREGROUND_DETACH

stopForeground(int)的標誌:如果設定,則先前提供給startForeground(int,Notification)的通知將與服務分離。

int

STOP_FOREGROUND_REMOVE

stopForeground(int)的標誌:如果設定,將刪除先前提供給startForeground(int,Notification)的通知。

4. 服務的生命週期

(1)Context.startService() 的生命週期。(和開啟者的生命週期無關,如果不顯示的停止 Service,Service 會一直執行。)

首次啟動 Service 會先呼叫 onCreate() ,然後呼叫 onStartCommand(),至此 Service 任務就啟動了。我們再次啟動相同 Service,你會發現只調用了 onStartCommand(),也就是說 onCreate() 只會被呼叫一次,onStartCommand()會呼叫多次。當我們停止 Service 會呼叫 onDestroy(),至此 Service 就停止了。生命週期結束!

  • 測試程式碼:
public class MyService extends Service {

    public static final String TAG = "My_Service";

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "MyService --> onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "MyService --> onStartCommand");
        return START_STICKY;
    }

    
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "MyService --> onDestroy");
    }
}
 Intent intent = new Intent(ServiceActivity.this, MyService.class);
 startService(intent);
stopService(intent);
  • 第一次啟動 Service 
 D/My_Service: MyService --> onCreate
 D/My_Service: MyService --> onStartCommand
  • 再次啟動相同 Service
 D/My_Service: MyService --> onStartCommand
  • 當我們停止服務 Service
 D/My_Service: MyService --> onDestroy

(2)Context.bindService() 的生命週期。(和開啟者的生命週期繫結,隨著開啟者的銷燬而銷燬)

首次啟動 Service 會呼叫 onCreate() ,同樣的也是隻會呼叫一次。隨後會呼叫 onBind() 。銷燬 Service 會呼叫先呼叫onUnbind(),隨後會呼叫 onDestroy()。至此生命週期結束!

  • 測試程式碼
public class MyService extends Service {

    public static final String TAG = "My_Service";

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG,"MyService --> onBind");
        return new MyBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG,"MyService --> onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "MyService --> onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "MyService --> onStartCommand");
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "MyService --> onDestroy");
    }

    public class MyBinder extends Binder implements IPersonalInif{

        @Override
        public String getName() {
            return "Test Name";
        }
    }

    public interface IPersonalInif {
        String getName();
    }
}
public class MyServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mInfoService = (MyService.IPersonalInif) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }

        @Override
        public void onBindingDied(ComponentName name) {

        }
}
Intent intent = new Intent(ServiceActivity.this, MyService.class);
mMyServiceConnection = new MyServiceConnection();
bindService(intent, mMyServiceConnection, Service.BIND_AUTO_CREATE);
Log.d(TAG,"IPersonalInif --> name --> " + mInfoService.getName());
unbindService(mMyServiceConnection);
  • 第一次啟動 Service
 D/My_Service: MyService --> onCreate
 D/My_Service: MyService --> onBind
  • 再次啟動相同服務 Service

logcat 沒有任何輸出,也就是再次啟動沒有任何回撥!

  • 我們嘗試獲取 Service 傳遞的值
 D/Service_Activity: IPersonalInif --> name --> Test Name
  • 解除 Service 的繫結
 D/My_Service: MyService --> onUnbind
 D/My_Service: MyService --> onDestroy

(3)先 Context.startService() 在 Context.bindService() 的生命週期。(這種方式的程式碼就不貼了,說說場景,和流程吧)

如果 Service 由某個客戶端通過 Context.startService() 啟動,接下來由其他客戶端通過 Context.bindService() 繫結到該 Service,然後在呼叫 unbindService() 解除該 Service,然後在通過 Context.bindService() 繫結到該 Service,那麼生命週期的步驟如下:

onCreate() --> onStartCommand --> onBind() --> onUnbind() --> onRebind()

注意:前提是 onUnbind() 返回 true,讀到這裡可能會有點疑惑,那就是我明明呼叫了 unbindService() 方法,系統為什麼不呼叫 Service 的 onDestroy() 呢?這是因為 Service 是我們先 Context.startService() 啟動的,所以系統只會呼叫 onUnbind(),不會呼叫 onDestroy()。(我們使用 Context.bindService() 繫結一個已經啟動的 Service ,系統只是會將 Service 內部的 IBinder 物件傳遞給 Activity,並不會將 Service 的生命週期和 Activity 的生命週期繫結,所以我們即使呼叫 unbindService(),也是不會銷燬 Service的)

至此,Service 的使用以及生命週期已經講解完了,希望對你有幫助!

歡迎加入Q群一起探討Android問題。Q群:653123508。