編輯:關於Android編程
與Activity
類似,Service
也是有生命周期的。在實現一個Service
的時候,可以覆蓋它的生命周期函數,當它進入不同生命狀態的時候,這些函數會被觸發,我們就可以在它不同的生命階段做不同的邏輯操作。
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}
因為Service
不像Activity
有需要顯示的界面,所以它的狀態少了很多,沒有onResume()
onPause()
等等與界面顯示相關的狀態。
這裡面的onStartCommand()
函數與onUnbind()
函數要特別注意,它們的返回值有特別的意義,會影響到Service
的生命周期,我們會在最後單獨解釋。
通過startService()
運行的Service
與通過bindService()
運行的Service
相比較,它們的生命周期有所不同。
假設Service
-MyService 還沒有被啟動過,我們來看看它被一個或多個組件使用startService()
stopService()
bindService()
unbindService()
這些方法後,生命周期會怎麼變化。
對於只使用startService()
和stopService()
來控制Service
的情況:
情況1
A -- startService() ->
MyService -- onCreate() ->
MyService -- onStartCommand() ->
A -- stopService() ->
MyService -- onDestroy()
情況2
A -- startService() ->
MyService -- onCreate() ->
MyService -- onStartCommand() ->
A -- startService() ->
MyService -- onStartCommand() ->
A -- stopService() ->
MyService -- onDestroy()
情況3
A -- startService() ->
MyService -- onCreate() ->
MyService -- onStartCommand() ->
B -- startService() ->
MyService -- onStartCommand() ->
A -- stopService() ->
MyService -- onDestroy()
情況4
A -- startService() ->
MyService -- onCreate() ->
MyService -- onStartCommand() ->
B -- startService() ->
MyService -- onStartCommand() ->
B -- stopService() ->
MyService -- onDestroy()
可以看出,
任意組件調用startService()
後,如果這個Service
還沒有創建,系統會首先創建-onCreate()
;
之後觸發onStartCommand()
;
任意組件調用stopService()
後,如果這個Service
還沒有被銷毀,系統會銷毀-onDestroy()
;
onStartCommand()
函數與onUnbind()
函數也會對生命周期有影響,所以這裡我們假設使用的是默認的返回值,
@Override
public boolean onUnbind(Intent intent) {
//實際上是返回false
return super.onUnbind(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//實際上是返回START_STICKY
return super.onStartCommand(intent, flags, startId);
}
組件觸發Service
運行的startService()
函數也會對生命周期有影響--第三個參數,所以這裡我們假設使用Context.BIND_AUTO_CREATE
,
bindService(i, mServiceConnection, Context.BIND_AUTO_CREATE);
那麼,對於只使用bindService()
和unbindService()
來控制Service
的情況:
情況1
C -- bindService() ->
MyService -- onCreate() ->
MyService -- onBind() ->
C -- onServiceConnected()被觸發 ->
C -- unbindService() ->
MyService -- onUnbind()
MyService -- onDestroy()
情況2
C -- bindService() ->
MyService -- onCreate() ->
MyService -- onBind() ->
C -- onServiceConnected()被觸發 ->
C -- bindService() ->
MyService -- 無變化
C -- unbindService() ->
MyService -- onUnbind()
MyService -- onDestroy()
情況3
C -- bindService() ->
MyService -- onCreate() ->
MyService -- onBind() ->
C -- onServiceConnected()被觸發 ->
D -- bindService() ->
MyService -- onBind() ->
D -- onServiceConnected()被觸發 ->
C -- unbindService() ->
MyService -- onUnbind()
D -- unbindService() ->
MyService -- onUnbind()
MyService -- onDestroy()
情況4
C -- bindService() ->
MyService -- onCreate() ->
MyService -- onBind() ->
C -- onServiceConnected()`被觸發 ->
D -- bindService() ->
MyService -- onBind() ->
D -- onServiceConnected()被觸發 ->
D -- unbindService() ->
MyService -- onUnbind()
C -- unbindService() ->
MyService -- onUnbind()
MyService -- onDestroy()
可以看出,
任意組件調用bindService()
後,如果這個Service
還沒有創建,系統會首先創建-onCreate()
;
之後觸發onBind()
;
之後組件的onServiceConnected()
被觸發,告知綁定成功;
任意已綁定的組件調用unbindService()
後,會觸發onUnbind()
;
如果這個Service
沒有與其他的組件綁定,那麼系統會銷毀-onDestroy()
;
對於使用了startService()
stopService()
與bindService()
和unbindService()
等兩種方式來控制Service
的情況:
情況1
A -- startService() ->
MyService -- onCreate() ->
MyService -- onStartCommand() ->
C -- bindService() ->
MyService -- onBind() ->
C -- onServiceConnected()被觸發 ->
C -- unbindService() ->
MyService -- onUnbind()
A -- stopService() ->
MyService -- onDestroy()
情況2
A -- startService() ->
MyService -- onCreate() ->
MyService -- onStartCommand() ->
C -- bindService() ->
MyService -- onBind() ->
C -- onServiceConnected()被觸發 ->
A -- stopService() ->
MyService -- 無變化
C -- unbindService() ->
MyService -- onUnbind()
MyService -- onDestroy()
情況3
C -- bindService() ->
MyService -- onCreate() ->
MyService -- onBind() ->
C -- onServiceConnected()被觸發 ->
A -- startService() ->
MyService -- onStartCommand() ->
C -- unbindService() ->
MyService -- onUnbind()
A -- stopService() ->
MyService -- onDestroy()
情況4
C -- bindService() ->
MyService -- onCreate() ->
MyService -- onBind() ->
C -- onServiceConnected()被觸發 ->
A -- startService() ->
MyService -- onStartCommand() ->
A -- stopService() ->
MyService -- 無變化
C -- unbindService() ->
MyService -- onUnbind()
MyService -- onDestroy()
可以看出,
當一個Service
被創建-onCreate()
之後;如果任意組件想要銷毀-onDestroy()
這個Service
;必須等到Service
與它關聯的所有組件切斷聯系(通過stopService()
或者unbindService()
)才行。
對Service
生命周期的影響還有其它的因素。
自定義Service
時,unbind()
函數的返回值對Service
的生命周期是有影響的。它會決定onRebind()
函數是否被調用。
前面我們都看到了在unbind()
返回false
時Service
生命周期的變化。在unbind()
返回true
時,它的周期變化如下,
A -- startService() ->
MyService -- onCreate() ->
MyService -- onStartCommand() ->
C -- bindService() ->
MyService -- onBind() ->
C -- onServiceConnected()被觸發 ->
C -- unbindService() ->
MyService -- onUnbind()
C -- bindService() ->
MyService -- onRebind() ->
C -- onServiceConnected()被觸發 ->
......
也就是說,假如一個Service
正在運行,此時有個組件C要綁定它,那麼會觸發onBind()
函數;如果C解除綁定,然後又再次綁定,那麼不會觸發onBind()
而是觸發onRebind()
函數。
在綁定Service
的時候,通常使用的Context.BIND_AUTO_CREATE
參數,
bindService(i, mServiceConnection, Context.BIND_AUTO_CREATE);
如果不使用Context.BIND_AUTO_CREATE
,那麼一個Service
在沒有被運行起來之前,使用bindService()
是不會讓Service
自動運行起來的。
但是如果設置上了這個參數,那麼就會讓它運行起來,然後進行綁定。
除了Context.BIND_AUTO_CREATE
參數,還有好些參數可以使用,
BIND_NOT_FOREGROUND,
BIND_ABOVE_CLIENT,
BIND_ALLOW_OOM_MANAGEMENT,
BIND_WAIVE_PRIORITY,
BIND_IMPORTANT,
BIND_ADJUST_WITH_ACTIVITY
可以用|
的方式同時使用其它的標志,例如,
bindService(i, mServiceConnection, Context.BIND_AUTO_CREATE|Context.BIND_NOT_FOREGROUND);
前面的onStartCommand()
返回值使用的是START_STICKY
,它對Service
的onStartCommand()
和周期都是有影響的。
Service
啟動之後,如果因為某種意外而停止運行(例如代碼寫的不好,Service
直接崩潰了),那麼系統要自動的把這個Service
再運行起來。這個時候,onStartCommand()
的返回值就決定了Service
重啟的行為,
START_STICKY
:Service
重啟(onCreate())之後,會觸發onStartCommand()
,但是此時onStartCommand()
的參數Intent
會變成空值,
public class MyService extends Service {
public MyService() {
}
......
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent == null) {
//因為這個Service在onStartCommand()返回的是START_STICKY,所以異常退出後,傳入的`intent`是空值
}
return START_STICKY;
}
}
START_NOT_STICKY
:Service
將不會被自動重啟,所以也就不會觸發onStartCommand()
;
START_REDELIVER_INTENT
:Service
重啟(onCreate())之後,會觸發onStartCommand()
,此時onStartCommand()
的參數Intent
不會變成空值。該Intent
將是以前想要啟動這個Service
的Intent
;如果以前有多個Intent
想要啟動它,那麼這裡會傳入最後一個,也就是最近的一個;
Android內核中判別啟動模式 問題出現在驅動組描述了一個問題是內核的一個驅動中設置的電壓值在正常模式和其它模式啟動時電壓值
效果圖:源碼:package com.zihao.radar;import android.app.Activity;import android.os.Bundle;i
因為公司業務需求 需要對一個屏幕進行截屏,但自帶的截屏功能是遠遠不夠項目的功能需求 ,我們是做一個畫板軟件 ,需要的像QQ那樣截屏之後 ,可以看到我們自定義的工具,有畫筆
Tab標簽頁是一個非常常用的控件,.net裡面就有multipage+tabstrip組合通過標簽的切換實現頁面的切換,同理html裡面我們常用frameset來