標籤:操作檔案 音樂 播放 生命週期 text ima 互動 機制 params
Service是什麼
Service(服務)是一個沒有使用者介面的在後台運行執行耗時操作的應用組件。其他應用組件能夠啟動Service,並且當使用者切換到另外的應用情境,Service將持續在後台運行。另外,一個組件能夠綁定到一個service與之互動(IPC機制),例如,一個service可能會處理網路操作,播放音樂,操作檔案I/O或者與內容提供者(content
provider)互動,所有這些活動都是在後台進行。
Service有兩種狀態,“啟動的”和“綁定”
Service預設跑在主線程,所以是在Service裡建立子線程而不是建立子線程跑Service。
Service的基本使用
定義一個服務:建立類繼承Service類
onBind方法是必須覆蓋的,而其他三個分別是建立時調用,銷毀時調用,啟動時調用
public class MyService extends Service { @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); }}
註冊Service,同樣是在設定檔中:
<service android:name=".MyService" />
啟動服務和停止服務:
switch (v.getId()) { case R.id.button1: Intent startIntent =new Intent(this,MyService.class); startService(startIntent); break; case R.id.button2: Intent stopIntent =new Intent(this,MyService.class); stopService(stopIntent); break; }
Service自己結束自己:stopSelf();
如果要服務完成什麼功能,寫在onStartCommand方法裡面即可。
Service與Activity通訊:
使用Binder對象可以進行兩者通訊,方法如下:
1. 在service裡面建立Binder類繼承Binder:
class MyBinder extends Binder{ public void MyStart(){ Log.d("Service", "MyStart: MyStart"); } }
- onBind方法中返回這個類的執行個體
private MyBinder mybinder; @Override public IBinder onBind(Intent intent) { return mybinder; }
- 接下來在活動中調用Service的方法,先綁定服務。
綁定用的參數connection;
private MyService.MyBinder myBinder; private ServiceConnection connection=new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) {//綁定調用 } @Override public void onServiceDisconnected(ComponentName name) {//j解除綁定調用 } };
綁定服務
case R.id.button3: Intent bindIntent=new Intent(this,MyService.class); bindService(bindIntent,connection,BIND_AUTO_CREATE); break; case R.id.button4: unbindService(connection); break;
調用服務的方法:
寫在onServiceConnected裡面:
@Override public void onServiceConnected(ComponentName name, IBinder service) { myBinder=(MyService.MyBinder) service; myBinder.MyStart(); }
服務的生命週期
通過這個圖可以看到,兩種啟動service的方式以及他們的生命週期,bind service的不同之處在於當綁定的組件銷毀後,對應的service也就被kill了。service的聲明周期相比與activity的簡單了許多,只要好好理解兩種啟動service方式的異同就行。
1.Service的基本認識1.1 Service是什嗎?
??Service(服務)是一個一種可以在後台執行長時間運行操作而沒有使用者介面的組件。它運行於UI線程,因此不能進行耗時的操作。
1.2 Service和Thread的區別
??Service的運行是在UI線程當中的,是絕對絕對不能進行耗時操作的,而Thread開啟的子線程則可以進行耗時操作,但是Thread開啟的子線程是不能直接對UI進行操作的,否則極有可能發生直接讓程式崩掉,這就是它們的區別。
2.啟動Service的2種方式2.1 startService()方法開啟Service
??步驟:
??a.定義一個類繼承Service。
??b.在AndroidManifest.xml檔案中配置該Service。
??c.使用Context的startService(Intent)方法啟動該Service。
??d.不再使用該Service時,調用Context的stopService(Intent)方法停止該Service。
2.2 bindService方法開啟Service(Activity與Service綁定)
??步驟:
??a.建立BinderService服務端,繼承自Service並在類中建立一個實現IBinder介面的實現執行個體對象並提供公用方法給用戶端調用。
??b.從onBind()回調方法返回此Binder執行個體。
??c.在用戶端中,從onServiceConnected回調方法接收Binder,並使用提供的方法調用綁定服務。
3.Service的生命週期
??服務的生命週期有兩種,因為服務可以跟Activity綁定起來,也可以不綁定,Activity和服務進行通訊的話,是需要把服務和Activity進行綁定的。因此服務的生命週期分為未綁定Activity的和綁定Activity的。
沒有綁定Activity的服務生命週期圖:
綁定Activity的服務生命週期圖:
1.通過Intent和startService()方法啟動了一個服務,接下來執行onCreate()方法,首次建立服務時,系統將調用此方法來執行一次性設定程式(在調用 onStartCommand() 或 onBind() 之前)。如果服務已在運行,則不會調用此方法。
2.當另一個組件(如 Activity)通過調用 startService() 請求啟動服務時,系統將調用此方法。一旦執行此方法,服務即會啟動並可在後台無限期運行。 如果您實現此方法,則在服務工作完成後,需要由您通過調用 stopSelf() 或 stopService() 來停止服務。(如果您只想提供綁定,則無需實現此方法。)
3.服務開始處於運行狀態。
4.某個操作導致服務停止,比如執行了方法stopService(),那麼服務接下來會執行onDestory()銷毀。服務應該實現此方法來清理所有資源,如線程、註冊的接聽程式、接收器等。 這是服務接收的最後一個調用。
5.服務被完全銷毀,下一步就是等待被記憶體回收行程回收了。
6.通過Intent和bindService()方法啟動了一個服務,接下來會執行onCreate()方法,首次建立服務時,系統將調用此方法來執行一次性設定程式(在調用 onStartCommand() 或 onBind() 之前)。如果服務已在運行,則不會調用此方法。
7.當另一個組件想通過調用 bindService() 與服務綁定(例如執行 RPC)時,系統將調用此方法。在此方法的實現中,您必須通過返回 IBinder 提供一個介面,供用戶端用來與服務進行通訊。請務必實現此方法,但如果您並不希望允許綁定,則應返回 null。
8.服務開始處於運行狀態。成功與Activity綁定。
9.某個操作導致服務解除綁定,比如執行了方法unbindService(),那麼服務接下來會解除與當前Activity的綁定。接下來服務將面臨銷毀。
10.服務執行onDestory()方法被銷毀。服務應該實現此方法來清理所有資源,如線程、註冊的接聽程式、接收器等。 這是服務接收的最後一個調用。
11.服務被完全銷毀,下一步就是等待被記憶體回收行程回收了。
關於服務,總結一下:
a. 被啟動的服務的生命週期:如果一個Service被某個Activity 調用 Context.startService 方法啟動,那麼不管是否有Activity使用bindService綁定或unbindService解除綁定到該Service,該Service都在後台運行。如果一個Service被startService 方法多次啟動,那麼onCreate方法只會調用一次,onStart將會被調用多次(對應調用startService的次數),並且系統只會建立Service的一個執行個體(因此你應該知道只需要一次stopService調用)。該Service將會一直在後台運行,而不管對應程式的Activity是否在運行,直到被調用stopService,或自身的stopSelf方法。當然如果系統資源不足,android系統也可能結束服務。
b. 被綁定的服務的生命週期:如果一個Service被某個Activity 調用 Context.bindService 方法綁定啟動,不管調用 bindService 調用幾次,onCreate方法都只會調用一次,同時onStart方法始終不會被調用。當串連建立之後,Service將會一直運行,除非調用Context.unbindService 中斷連線或者之前調用bindService 的 Context 不存在了(如Activity被finish的時候),系統將會自動停止Service,對應onDestroy將被調用。
c. 被啟動又被綁定的服務的生命週期:如果一個Service又被啟動又被綁定,則該Service將會一直在後台運行。並且不管如何調用,onCreate始終只會調用一次,對應startService調用多少次,Service的onStart便會調用多少次。調用unbindService將不會停止Service,而必須調用 stopService 或 Service的 stopSelf 來停止服務。
d. 當服務被停止時清除服務:當一個Service被終止(1、調用stopService;2、調用stopSelf;3、不再有綁定的串連(沒有被啟動))時,onDestroy方法將會被調用,在這裡你應當做一些清除工作,如停止在Service中建立並啟動並執行線程。
特別注意:
1、你應當知道在調用 bindService 綁定到Service的時候,你就應當保證在某處調用 unbindService 解除綁定(儘管 Activity 被 finish 的時候綁定會自動解除,並且Service會自動停止);
2、你應當注意 使用 startService 啟動服務之後,一定要使用 stopService停止服務,不管你是否使用bindService;
3、同時使用 startService 與 bindService 要注意到,Service 的終止,需要unbindService與stopService同時調用,才能終止 Service,不管 startService 與 bindService 的調用順序,如果先調用 unbindService 此時服務不會自動終止,再調用 stopService 之後服務才會停止,如果先調用 stopService 此時服務也不會終止,而再調用 unbindService 或者 之前調用 bindService 的 Context 不存在了(如Activity 被 finish 的時候)之後服務才會自動停止;
4、當在旋轉手機螢幕的時候,當手機螢幕在“橫”“豎”變換時,此時如果你的 Activity 如果會自動旋轉的話,旋轉其實是 Activity 的重新建立,因此旋轉之前的使用 bindService 建立的串連便會斷開(Context 不存在了),對應服務的生命週期與上述相同。
5、在 sdk 2.0 及其以後的版本中,對應的 onStart 已經被否決變為了 onStartCommand,不過之前的 onStart 任然有效。這意味著,如果你開發的應用程式用的 sdk 為 2.0 及其以後的版本,那麼你應當使用 onStartCommand 而不是 onStart。
Service 與 Thread的區別
- 結論:
Service
與 Thread
無任何關係
- 之所以有不少人會把它們聯絡起來,主要因為
Service
的後台概念
後台:背景工作運行完全不依賴UI
,即使Activity被銷毀 / 程式被關閉,只要進程還在,背景工作就可繼續運行
- 註:一般會將
Service
和 Thread
聯合著用,即在Service
中再建立一個子線程(背景工作執行緒)去處理耗時操作邏輯,如下代碼:
@Override public int onStartCommand(Intent intent, int flags, int startId) { //建立背景工作執行緒 new Thread(new Runnable() { @Override public void run() { // 開始執行背景工作 } }).start(); return super.onStartCommand(intent, flags, startId); } class MyBinder extends Binder { public void service_connect_Activity() { //建立背景工作執行緒 new Thread(new Runnable() { @Override public void run() { // 執行具體的下載任務 } }).start(); } }
Android面試三之Service