深刻理解Android的startservice和bindservice

1、首先,讓咱們確認下什麼是service?
        service就是android系統中的服務,它有這麼幾個特色:它沒法與用戶直接進行交互、它必須由用戶或者其餘程序顯式的啓動、它的優先級比較高, 它比處於前臺的應用優先級低,可是比後臺的其餘應用優先級高,這就決定了當系統由於缺乏內存而銷燬某些沒被利用的資源時,它被銷燬的機率很小哦。
2、那麼,何時,咱們須要使用service呢?
        咱們知道,service是運行在後臺的應用,對於用戶來講失去了被關注的焦點。這就跟咱們打開了音樂播放以後,便想去看看圖片,這時候咱們還不想音樂停 止,這裏就會用到service;又例如,咱們打開了一個下載連接以後,咱們確定不想瞪着眼睛等他下載完再去作別的事情,對吧?這時候若是咱們想手機一邊 在後臺下載,一邊可讓我去看看新聞啥的,就要用到service。
3、service分類:
       通常咱們認爲service分爲兩類,        <!-- service配置結束-->
第三步:在activity中進行啓動、綁定、解綁或者中止service。
        (不少書上說,service與用戶是不能交互的,其實這話很不正確,咱們徹底能夠經過activity與service進行交互!我認爲,確切的說法應該是service與用戶不能進行直接的交互)。
android

-----------------------------安全

bindService介紹

1、bindService簡介app

bindService是綁定Service服務,執行service服務中的邏輯流程。ide

service經過Context.startService()方法開始,經過Context.stopService()方法中止;也能夠經過Service.stopSelf()方法或者Service.stopSelfResult()方法來中止本身。只要調用一次stopService()方法即可以中止服務,不管以前它被調用了多少次的啓動服務方法。工具

客戶端創建一個與Service的鏈接,並使用此鏈接與Service進行通話,經過Context.bindService()方法來綁定服務,Context.unbindService()方法來關閉服務。多個客戶端能夠綁定同一個服務,若是Service還未被啓動,bindService()方法能夠啓動服務。學習

上面startService()和bindService()兩種模式是徹底獨立的。你能夠綁定一個已經經過startService()方法啓動的服務。例如:一 個後臺播放音樂服務能夠經過startService(intend)對象來播放音樂。可能用戶在播放過程當中要執行一些操做好比獲取歌曲的一些信息,此時 activity能夠經過調用bindServices()方法與Service創建鏈接。這種狀況下,stopServices()方法實際上不會中止 服務,直到最後一次綁定關閉。this

若是沒有程序中止它或者它本身中止,service將一直運行。在這種模式 下,service開始於調用Context.startService() ,中止於Context.stopService(). service能夠經過調用Android Service 生命週期() 或 Service.stopSelfResult()中止本身。無論調用多少次startService() ,只須要調用一次 stopService() 就能夠中止service。spa

能夠經過接口被外部程序調用。外部程序創建到service的鏈接,經過 鏈接來操做service。創建鏈接調開始於Context.bindService(), 結束於Context.unbindService(). 多個客戶端能夠綁定到同一個service,若是service沒有啓動, bindService() 能夠選擇啓動它。線程

這2種模式不是徹底分離的。你能夠能夠綁定到一個經過startService()啓動的服務。如 一個intent想要播放音樂,經過startService() 方法啓動後臺播放音樂的service。而後,也許用戶想要操做播放器或者獲取當前正在播放的樂曲的信息,一個activity就會經過 bindService()創建一個到此service的鏈接. 這種狀況下 stopService() 在所有的鏈接關閉後纔會真正中止service。code

2、bindService啓動流程

context.bindService()  ——> onCreate()  ——> onBind()  ——> Service running  ——> onUnbind()  ——> onDestroy()  ——> Service stop

onBind()將返回給 客戶端一個IBind接口實例,IBind容許客戶端回調服務的方法,好比獲得Service的實例、運行狀態或其餘操做。這個時候把調用者 (Context,例如Activity)會和Service綁定在一塊兒,Context退出了,Srevice就會調用 onUnbind->onDestroy相應退出。

因此調用bindService的生命週期爲:onCreate --> onBind(只一次,不可屢次綁定) --> onUnbind --> onDestory。

在Service每一次的開啓關閉過程當中,只有onStart可被屢次調用(經過屢次startService調用),其餘onCreate,onBind,onUnbind,onDestory在一個生命週期中只能被調用一次。

3、bindService生命週期

像一個activity那樣,一個service有些能夠用來改變狀態的生命週期方法,可是比activity的方法少,service生命週期方法只有三個public

  void onCreate()

  void onStart(Intent intent)

  void onDestroy()

經過實現這三個生命週期方法,你能夠監聽service的兩個嵌套循環的生命週期:

一、整個生命週期

service 的整個生命週期是在onCreate()和onDestroy()方法之間。和activity同樣,在onCreate()方法裏初始化,在 onDestroy()方法裏釋放資源。例如,一個背景音樂播放服務能夠在onCreate()方法裏播放,在onDestroy()方法裏中止。

二、活動的生命週期

service 的活動生命週期是在onStart()以後,這個方法會處理經過startServices()方法傳遞來的Intent對象。音樂service能夠通 過開打intent對象來找到要播放的音樂,而後開始後臺播放。注: service中止時沒有相應的回調方法,即沒有onStop()方法,只有onDestroy()銷燬方法。

任何服務不管它怎樣創建,默認客戶端均可以鏈接,因此任何service都可以接收onBind()和onUnbind()方法

onCreate()方法和onDestroy()方法是針對全部的services,不管它們是否啓動,經過Context.startService()和Context.bindService()方法均可以訪問執行。然而,只有經過startService()方法啓動service服務時纔會調用onStart()方法
 

若是一個service容許別人綁定,那麼須要實現如下額外的方法:

      IBinder onBind(Intent intent)

      boolean onUnbind(Intent intent)

      void onRebind(Intent intent)

onBind()回調方法會繼續傳遞經過bindService()傳遞來的intent對象

onUnbind()會處理傳遞給unbindService()的intent對象。若是service容許綁定,onBind()會返回客戶端與服務互相聯繫的通訊句柄(實例)。

若是創建了一個新的客戶端與服務的鏈接,onUnbind()方法能夠請求調用onRebind()方法。

4、bindService和startservice示例

(1)mainactivity

public class MainActivity extends Activity {
    Button startServiceButton;// 啓動服務按鈕
    Button shutDownServiceButton;// 關閉服務按鈕
    Button startBindServiceButton;// 啓動綁定服務按鈕
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        getWidget();
        regiestListener();
    }

    /** 得到組件 */
    public void getWidget() {
        startServiceButton = (Button) findViewById(R.id.startServerButton);
        startBindServiceButton = (Button) findViewById(R.id.startBindServerButton);
        shutDownServiceButton = (Button) findViewById(R.id.sutdownServerButton);
    }

    /** 爲按鈕添加監聽 */
    public void regiestListener() {
        startServiceButton.setOnClickListener(startService);
        shutDownServiceButton.setOnClickListener(shutdownService);
        startBindServiceButton.setOnClickListener(startBinderService);
    }
    
    
    /** 啓動服務的事件監聽 */
    public Button.OnClickListener startService = new Button.OnClickListener() {
        public void onClick(View view) {
            /** 單擊按鈕時啓動服務 */
            Intent intent = new Intent(MainActivity.this,
                    CountService.class);
            startService(intent);
            
            Log.v("MainStadyServics", "start Service");
        }
    };
    /** 關閉服務 */
    public Button.OnClickListener shutdownService = new Button.OnClickListener() {
        public void onClick(View view) {
            /** 單擊按鈕時啓動服務 */
            Intent intent = new Intent(MainActivity.this,
                    CountService.class);
            /** 退出Activity是,中止服務 */
            stopService(intent);
            Log.v("MainStadyServics", "shutDown serveice");
        }
    };
    /** 打開綁定服務的Activity */
    public Button.OnClickListener startBinderService = new Button.OnClickListener() {
        public void onClick(View view) {
            /** 單擊按鈕時啓動服務 */
            Intent intent = new Intent(MainActivity.this, UseBrider.class);
            startActivity(intent);
            Log.v("MainStadyServics", "start Binder Service");
        }
    };
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

 

(2)service

package com.example.testservice;

/**引入包*/
import android.app.Service;// 服務的類
import android.os.IBinder;
import android.os.Binder;
import android.content.Intent;
import android.util.Log;

/** 計數的服務 */
public class CountService extends Service {
    /** 建立參數 */
    boolean threadDisable;
    int count;

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

    public void onCreate() {
        super.onCreate();
        /** 建立一個線程,每秒計數器加一,並在控制檯進行Log輸出 */
        new Thread(new Runnable() {
            public void run() {
                while (!threadDisable) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {

                    }
                    count++;
                    Log.v("CountService", "Count is" + count);
                }
            }
        }).start();
    }

    public void onDestroy() {
        super.onDestroy();
        /** 服務中止時,終止計數進程 */
        this.threadDisable = true;
    }

    public int getConunt() {
        return count;
    }

//此方法是爲了能夠在Acitity中得到服務的實例   

class ServiceBinder extends Binder {
        public CountService getService() {
            return CountService.this;
        }
    }
}

 

(3)bindservice(必定要記着這個是要得到,連接的對象)

package com.example.testservice;

/**引入包*/
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

/** 經過bindService和unBindSerivce的方式啓動和結束服務 */
public class UseBrider extends Activity {
    /** 參數設置 */
    CountService countService;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new UseBriderFace(this));
        
        Intent intent = new Intent(UseBrider.this, CountService.class);
        /** 進入Activity開始服務 */
        bindService(intent, conn, Context.BIND_AUTO_CREATE);

    }

    
    private ServiceConnection conn = new ServiceConnection() {
        /** 獲取服務對象時的操做 */
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            countService = ((CountService.ServiceBinder) service).getService();

        }

        /** 沒法獲取到服務對象時的操做 */
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            countService = null;
        }

    };

    protected void onDestroy() {
        super.onDestroy();
        this.unbindService(conn);
        Log.v("MainStadyServics", "out");
    }
}

 

注意:這個地方有朋友可能會出現onServiceConnected不調用的狀況。

這個問題當調用bindService方法後就會回調Activity的onServiceConnected,在這個方法中會向Activity中傳遞一個IBinder的實例,Acitity須要保存這個實例

在Service中須要建立一個實現IBinder的內部類(這個內部類不必定在Service中實現,但必須在Service中建立它)。

在OnBind()方法中需返回一個IBinder實例,否則onServiceConnected方法不會調用。

不過,我在這裏傳遞null也可以調用,你們根據狀況進行斷定吧,若是是返回一個ibinder實例的話,示例代碼以下:

public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        System.out.println("onBind.....");
         IBinder result = null;  
            if ( null == result ) result = new MyBinder() ;
        Toast.makeText(this, "onBind",Toast.LENGTH_LONG);
        return result;
    }

 

至於startservice和bindservice的使用場景,有網友這麼說:

1.經過startservice開啓的服務.一旦服務開啓, 這個服務和開啓他的調用者之間就沒有任何的關係了.
調用者不能夠訪問 service裏面的方法. 調用者若是被系統回收了或者調用了ondestroy方法, service還會繼續存在 
2.經過bindService開啓的服務,服務開啓以後,調用者和服務之間 還存在着聯繫 ,
一旦調用者掛掉了.service也會跟着掛掉 .

 

示例下載地址:http://pan.baidu.com/share/link?shareid=1614272126&uk=1428765741

還有一個多樣化的demo學習地址:http://pan.baidu.com/share/link?shareid=1616100229&uk=1428765741

 

內容來源於互聯網,感謝做者的無私提供

相關文章
相關標籤/搜索