1. 程式人生 > >Android面試三之Service

Android面試三之Service

UNC roi upload div 也不會 但是 () 調用順序 總結

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" />
  • 1

啟動服務和停止服務:

 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");
        }
    }
  1. onBind方法中返回這個類的實例
private MyBinder mybinder;
    @Override
    public IBinder onBind(Intent intent) {
        return mybinder;
    }
  1. 接下來在活動中調用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的區別

  • 結論:ServiceThread 無任何關系
  • 之所以有不少人會把它們聯系起來,主要因為Service的後臺概念

後臺:後臺任務運行完全不依賴UI,即使Activity被銷毀 / 程序被關閉,只要進程還在,後臺任務就可繼續運行

  • 關於二者的異同,具體如下圖:
技術分享圖片 示意圖
  • 註:一般會將 ServiceThread聯合著用,即在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