日報2015/10/16(極客學院安卓視頻學習)

啓動 Service 並傳遞數據(通過Intent)

啓動的時候

Intent i= new Intent(MainActivity.this, MyService.class);
i.putExtra("data",editText.getText().toString());
startService(i);

在MyService裏面,因爲之前是startService,與之對應的是onStartCommand,所以在這裏面接受數據就好啦

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        data = intent.getStringExtra("data");

        return super.onStartCommand(intent, flags, startId);
    }

啓動一次服務,輸入文本,再次點擊啓動按鈕

10-16 22:07:03.825  10312-10312/com.jackie.courseservice V/jackie﹕ 開始服務
10-16 22:07:03.830  10312-10312/com.jackie.courseservice V/jackie﹕ Service created
10-16 22:07:03.830  10312-10312/com.jackie.courseservice V/jackie﹕ Command started
10-16 22:07:03.835  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...默認信息
10-16 22:07:05.835  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-16 22:07:07.835  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-16 22:07:09.835  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-16 22:07:11.835  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-16 22:07:13.835  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-16 22:07:15.835  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-16 22:07:17.840  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-16 22:07:19.835  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-16 22:07:20.630  10312-10312/com.jackie.courseservice V/jackie﹕ 開始服務
10-16 22:07:21.835  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...修改後再次啓動
10-16 22:07:23.840  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...修改後再次啓動
10-16 22:07:25.840  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...修改後再次啓動
10-16 22:07:27.840  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...修改後再次啓動
10-16 22:07:29.840  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...修改後再次啓動
10-16 22:07:31.840  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...修改後再次啓動
10-16 22:07:33.840  10312-10746/com.jackie.courseservice V/jackie﹕ 服務正在運行...修改後再次啓動
10-16 22:07:33.920  10312-10312/com.jackie.courseservice V/jackie﹕ 停止服務
10-16 22:07:33.925  10312-10312/com.jackie.courseservice V/jackie﹕ Service destroyed

這裏寫圖片描述

綁定 Service 進行通信(上)

除了使用Intent進行通信,也可以通過Service中的Binder來通信,這裏就需要將Activity和Service綁定(bind)在一起了

1、綁定服務

bindService(new Intent(MainActivity.this, MyService.class), this, BIND_AUTO_CREATE);

2、Service中設置一個成員變量data,來呈現兩邊數據的同步,並且,在Service創建後啓動一個線程,不停地打印這個data,觀察它的變化

    public String data = "默認信息";
    ...
                while (isRunning){
                    Log.v("jackie","服務正在運行..."+data);
                    try {
                        sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

3、關鍵:在Service裏面自己寫一個MyBinder,繼承Binder,裏面寫一個方法,用來設置成員變量data的值,並且,在onBind(Intent intent)方法裏面返回這個自己定義的MyBinder

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

    }

這個返回的自定義Binder就是Service和Activity溝通的橋樑

4、由於在爲MainActivity綁定Service的時候,是將MainActivity作爲一個ServiceConnection傳參,所以在這個必須重寫的方法裏,IBinder service 其實就是之前返回的MyBinder

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        //這裏的binder用於接受onBinder返回的MyBinder
        binder = (MyService.MyBinder) service;
    }

5、通過這個binder,來在按鈕點擊事件裏改變Service中data的值

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

這樣就實現了在Activity裏面改變Service中的成員變量,關鍵就在於這個binder

10-16 21:57:25.795   27876-5582/com.jackie.courseservice V/jackie﹕ 服務正在運行...默認信息
10-16 21:57:27.795   27876-5582/com.jackie.courseservice V/jackie﹕ 服務正在運行...默認信息
10-16 21:57:29.800   27876-5582/com.jackie.courseservice V/jackie﹕ 服務正在運行...默認信息
10-16 21:57:31.795   27876-5582/com.jackie.courseservice V/jackie﹕ 服務正在運行...默認信息
10-16 21:57:31.960  27876-27876/com.jackie.courseservice W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
10-16 21:57:33.800   27876-5582/com.jackie.courseservice V/jackie﹕ 服務正在運行...默認信息
10-16 21:57:35.540  27876-27876/com.jackie.courseservice V/jackie﹕ 同步數據
10-16 21:57:35.795   27876-5582/com.jackie.courseservice V/jackie﹕ 服務正在運行...我是綁定後修改的值
10-16 21:57:37.795   27876-5582/com.jackie.courseservice V/jackie﹕ 服務正在運行...我是綁定後修改的值
10-16 21:57:39.795   27876-5582/com.jackie.courseservice V/jackie﹕ 服務正在運行...我是綁定後修改的值
10-16 21:57:41.800   27876-5582/com.jackie.courseservice V/jackie﹕ 服務正在運行...我是綁定後修改的值

這裏寫圖片描述


綁定 Service 進行通信(下)

上面我們通過binder對Service裏面的數據進行了訪問操作,並且在LogCat裏面打印了這個數據,那麼如果不想看Log,直接把數據呈現在用戶可以交互到的Activity豈不是更加方便嗎,所以,這裏可以嘗試一下,如何偵聽被綁定的 Service 的內部狀態。

還是之前的打印線程,給一個count,每次加一

...
count++;
Log.v("jackie","服務正在運行..."+count);
...

在Activity裏面弄一個顯示區域顯示這個count

這個實現的關鍵就是:回調機制 Callback,Service裏面那個自己定義的MyBinder裏面寫一個獲取當前Service的方法

        public MyService getService() {
            return MyService.this;
        }

然後定義一個接口Callback,並且該Service要有一個Callback類型的成員變量

    private Callback callback;

    public static interface Callback {
        public void onDataChange(String data);
    }

然後線程打印的時候,循環裏面有一句

count++;
if (callback != null) {
    callback.onDataChange("服務正在運行..." + count);
}

在Activity中通過獲取Callback並重寫onDataChange方法就可以監聽線程裏面count的值了

由於其他線程是不可以改變UI線程的內容的,所以我們需要Handler來通知主線程改變TextView的內容

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        binder = (MyService.MyBinder) service;
        binder.getService().setCallback(new MyService.Callback() {
            @Override
            public void onDataChange(String data) {
                Message msg = new Message();
                Bundle b = new Bundle();
                b.putString("data", data);
                msg.setData(b);
                handler.sendMessage(msg);
            }
        });
//        Log.v("jackie", "Service Connected");

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

這裏寫圖片描述
這裏寫圖片描述

po主要說一句,Callback太特麼好用了!Activity可以爲自己給綁定的Service的Callback重寫自己需要的功能,然後MyService啓動之後它的Callback執行的就是重寫過的功能了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章