Service啟動和數據傳遞


Service是四大組件之一,Service是服務的意思,像Windows上面的服務一樣,服務是在后台運行的,承擔着靜悄悄,默默的在后台付出的工作。

在開發過程中Service可以在很多地方使用,比如播放多媒體的時候用戶啟動了其他Activity ,這個時候程序要在后台繼續播放;或者在后台記錄用戶地理位置的改變,或者啟動服務來一直監聽某種事件等。雖然Service存在的價值不如Activity,但是一般都讓Service執行耗時時間較長的操作。下面我們詳細介紹一下Service。

一,啟動Service主要有兩種方式:

  1)  startService(),調用者與服務之間沒有關聯,即時調用者退出,服務仍然可以運行。

    被啟動的服務是由調用startService方法啟動的,該方法會調用生命周期方法onStartComment(),當服務被啟動后,改服務的生命周期與其他組件沒有關系,即使啟動服務的組件(Activity,BroadcastReciver)已經被銷毀,該服務還是可以在后台無限期的運行,除非調用stopService()來停止服務。

      2)  bindService(),調用者與服務綁定在一起,調用者一旦退出(啟動Service的Activity退出,Service也退出),服務也退出。

    綁定服務是調用bindService方法啟動的,綁定調用了onBind生命周期方法,改方法返回IBinder對象,同時啟動服務的Activity必須提供ServiceConnect接口的實現類,它有兩個方法onServiceConnected和onServiceDisconnected方法,監聽Activity與服務類之間的連接。

二,Service的生命周期:

  

 

1、Started Service的生命周期:
  • onCreate():創建服務
  • onStartCommand():服務開始運行(在2.0以前版本中,使用onStart()回調方法)
  • onDestroy() :服務被停止
【詳細說明:】
  • 在程序中調用:context.startService() 會觸發執行Service生命周期中的onCreate()、onStartCommand()回調方法,此時服務就開始正式運行;
  • 如果Service還沒有運行,則android先調用onCreate()然后調用onStartCommand();如果Service已經運行,則只調用onStartCommand(),所以一個Service的onStartCommand方法可能會重復調用多次;
  • 如果在程序中調用:context.stopService()會觸發執行Service生命周期中的onDestroy()回調方法,會讓服務停止;
  • stopService()的時候直接onDestroy,如果是調用者自己直接退出而沒有調用stopService()的話,Service會一直在后台運行。該Service的調用者再啟動該Service后可以通過stopService關閉Service;
  • 所以StartService的生命周期為:onCreate --> onStartCommand(可多次調用) --> onDestroy。
 
2、Bound Service的生命周期:
  • onCreate():創建服務
  • onBind():綁定服務,服務開始運行
  • onUnbind():取消綁定
  • onDestroy() :服務被停止
【詳細說明:】
  • 在程序中調用:context.bindService()會觸發執行Service生命周期中的onCreate()、onBind()回調方法,此時服務開始運行;
  • onBind將返回給客戶端一個IBind接口實例,IBind允許客戶端回調服務的方法,比如得到Service運行的狀態或其他操作。此后調用者(Context,例如Activity)會和Service綁定在一起;
  • 如果調用Service的調用者Context退出了,那么會依次調用Service生命周期中的onUnbind()、onDestroy()回調方法,會讓服務停止;    
  • 所以BindService的生命周期為:onCreate --> onBind(只一次,不可多次綁定) --> onUnbind --> onDestory。

三,綁定Service通信:

  1,向Service內部傳遞數據:

     創建一個Activity,用來啟動Service,我們在Activity里面創建一個布局,如下所示:

      

   EditText用來動態改變向Service里面數據,點擊同步數據按鈕用來將Activity里面的數據傳遞到Service里面。

   將數據同步到Service里面需要利用服務得IBinder對象。下面是我的服務類:

public class MyService extends Service {

    private boolean running = false;
    private String data = "默認信息";//創建一個字符串,用來接收數據

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
    
return new Binder();//④返回Binder的事例 } /** *②創建一個類繼承Binder,來對data數據進行更新 */ public class Binder extends android.os.Binder{ public void setData(String data){//③寫一個公共方法,用來對data數據賦值。 MyService.this.data = data; } } @Override public void onCreate() { super.onCreate(); running = true; new Thread(){ //①創建一個Thread用來數據傳遞進來的data數據。 @Override public void run() { super.run(); while (running){ System.out.println(data);//打印數據 try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } @Override public void onDestroy() { super.onDestroy(); running = false; }

在Activity中,需要實現ServiceConnection接口,並且在綁定成功的onServiceConnected方法中初始化Binder對象:

1,首先定義變量 private MyService.Binder binder = null;

2,在onServiceConnected方法中進行初始化:

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

3,點擊同步數據按鈕向Service里面賦值:

  binder.setData(editText.getText().toString());

具體代碼如下所示:

public class MainActivity extends AppCompatActivity implements OnClickListener, ServiceConnection {
    private EditText editText;
    private MyService.Binder binder = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_main);
        editText = (EditText) findViewById(R.id.edit);
        findViewById(R.id.bindService).setOnClickListener(this);
        findViewById(R.id.unbindService).setOnClickListener(this);
        findViewById(R.id.btnSync).setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bindService://點擊綁定服務按鈕
                bindService(new Intent(this,MyService.class),this, Context.BIND_AUTO_CREATE);
                break;
            case R.id.unbindService://解除綁定服務按鈕
                unbindService(this);
                break;
            case R.id.btnSync://同步數據按鈕
                if (binder != null){
                    binder.setData(editText.getText().toString());
                }
                break;
        }
    }
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        binder = (MyService.Binder) service;
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
}
View Code

這樣就完成了想Service內部的數據傳遞。

四,service向Activity傳遞數據

 上面介紹了Activity向Service內部傳值,現在我們來介紹一下Service向Activity傳遞數據:

 從Service向Activity傳值,我們需要利用接口,首先在MyService里面自定義一個接口CallBack,實現onDataChanged方法;  

 public static  interface  CallBack{
         void onDataChanged(String data);
    }

在MyService里面定義CallBack類型的變量,並且實現它的set方法,來獲得CallBack的實例。在MyService的Oncrate方法中定義一個變量i,然后動態改變i的數值,然后通過callback.onDataChanged("數據="+i) 將數據進行傳遞。具體實現方法如下所示:

public class MyService extends Service {

    private boolean running = false;

    public MyService() {
    }

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

    /**
     *創建一個類繼承Binder,來進行
     */
    public class Binder extends android.os.Binder{
        public MyService getService(){
            return MyService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        running = true;
        new Thread(){
            @Override
            public void run() {
                super.run();
                int i = 0;
                while (running){
                    i++;
                    if (callback != null){
                        callback.onDataChanged("數據="+i);
                    }
                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        running = false;
    }

    private CallBack callback = null;

    public void setCallback(CallBack callback) {
        this.callback = callback;
    }

    public static  interface  CallBack{
         void onDataChanged(String data);
    }
}
View Code

在Activity中我們需要 1,獲得Myservice的實例來調用serCallBack方法,所以我在MyService的Binder方法里面添加了獲取MyService實例的方法。

2,將調用CallBack接口之后onDataChanged方法返回的值賦值到TextView上面,還是用到了servce的IBinder對象。

具體實現方法如下所示:

public class MainActivity extends AppCompatActivity implements OnClickListener, ServiceConnection {

    private TextView textView;
    private MyService.Binder binder = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_main);
        textView = (TextView) findViewById(R.id.tvout);
        findViewById(R.id.bindService).setOnClickListener(this);
        findViewById(R.id.unbindService).setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bindService://點擊綁定服務按鈕
                bindService(new Intent(this,MyService.class),this, Context.BIND_AUTO_CREATE);
                break;
            case R.id.unbindService://解除綁定服務按鈕
                unbindService(this);
                break;
        }
    }
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        binder = (MyService.Binder) service;

        binder.getService().setCallback(new MyService.CallBack() {
            @Override
            public void onDataChanged(String data) {//因為在Service里面賦值data是在Thread中進行的,所以我們不能直接在這里將返回的值展示在TextView上。
                Message msg = new Message();
                Bundle bundle = new Bundle();
                bundle.putString("data",data);
                msg.setData(bundle);
                handler.sendMessage(msg);
            }
        });
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }

    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            textView.setText(msg.getData().getString("data"));
        }
    };
}
View Code

 

 

 

源碼地址:

Activity向Service傳遞數據:http://download.csdn.net/detail/jingsummer/9372505

Service里面的數據傳遞到Activity中:http://download.csdn.net/detail/jingsummer/9372513

 

 

 

 

 

 

      

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM