Activity与Service之间的数据通信

我们知道启动Service有两种方法:在Activity里调用startService或者BindService方法。

那二者之间的不同之处是什么呢?用代码来说话吧。

 

Activity:
public class MainActivity extends BaseActivity implements HandlerCallback {

    private TextView mTextView;
    private Button mBtn;
    private Button mBindBtn;
    private Button mUnBindBtn;
    private Button mStartBtn;
    private Button mStopBtn;

    private Intent mIntent;
    private MyServiceConnection mMyServiceConnection;

    private MyService.MyBinder myBinder;
    private MyService myService;

    private NoLeakHandler mHandler;

    private View.OnClickListener mListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn:
                    if (myBinder != null) {
                        myBinder.setData("DEMO");
                    }
                    break;
                case R.id.bind_btn:
                    bindService(mIntent, mMyServiceConnection, BIND_AUTO_CREATE);
                    break;
                case R.id.unbind_btn:
                    unbindService(mMyServiceConnection);
                    break;
                case R.id.start_btn:
                    mIntent.putExtra("data", "data");
                    startService(mIntent);
                    break;
                case R.id.stop_btn:
                    stopService(mIntent);
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView) findViewById(R.id.textview);
        mBtn = (Button) findViewById(R.id.btn);
        mBtn.setOnClickListener(mListener);
        mBindBtn = (Button) findViewById(R.id.bind_btn);
        mBindBtn.setOnClickListener(mListener);
        mUnBindBtn = (Button) findViewById(R.id.unbind_btn);
        mUnBindBtn.setOnClickListener(mListener);
        mStartBtn = (Button) findViewById(R.id.start_btn);
        mStopBtn = (Button) findViewById(R.id.stop_btn);
        mStartBtn.setOnClickListener(mListener);
        mStopBtn.setOnClickListener(mListener);

        mHandler = new NoLeakHandler(this);
        mIntent = new Intent(this, MyService.class);
        mMyServiceConnection = new MyServiceConnection();
    }

    @Override
    public void callback(Message message) {
        mTextView.setText((String) message.getData().get("data"));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }

    private static class NoLeakHandler extends Handler {
        private WeakReference mWeakReference;

        public NoLeakHandler(T t) {
            mWeakReference = new WeakReference(t);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            T t = mWeakReference.get();
            if (null != t) {
                t.callback(msg);
            }
        }
    }

    private class MyServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myBinder = (MyService.MyBinder) service;
            myService = myBinder.getMyService();
            myService.setCallback(new MyService.Callback() {
                @Override
                public void receive(String rec) {
                    Message msg = new Message();
                    Bundle bundle = new Bundle();
                    bundle.putString("data", rec);
                    msg.setData(bundle);
                    mHandler.sendMessage(msg);
                }
            });
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            myBinder = null;
        }

        @Override
        public void onBindingDied(ComponentName name) {

        }
    }
}
Service:

public class MyService extends Service {

    private String mStr;
    private Callback callback;
    private int i = 0;
    private boolean stop = false;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.w("onBind");
        return new MyBinder();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.w("onCreate()");
        Thread thread = new Thread() {
            @Override
            public void run() {
                super.run();
                while (!stop) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.i("999");
                    if (null != callback) {
                        callback.receive(mStr + (i++));
                    }
                }
            }
        };
        thread.start();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.w("onStartCommand");
        mStr = intent.getStringExtra("data");
        return super.onStartCommand(intent, flags, startId);
    }

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

    @Override
    public void onDestroy() {
        Log.w("onDestroy()");
        stop = true;
        super.onDestroy();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.w("onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onRebind(Intent intent) {
        Log.w("onRebind");
        super.onRebind(intent);
    }

    public interface Callback {
        void receive(String rec);
    }

    public class MyBinder extends Binder {

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

        public void setData(String s) {
            mStr = s;
        }
    }
}

(1)通过startService来启动Service

  Log:

10-21 15:42:47.705 6821-6821/gryl.client W/GRYL: onCreate()
10-21 15:42:47.706 6821-6821/gryl.client W/GRYL: onStartCommand
10-21 15:42:48.706 6821-20260/gryl.client I/GRYL: 999
10-21 15:42:49.707 6821-20260/gryl.client I/GRYL: 999
调用stopService后:

10-21 15:42:56.844 6821-6821/gryl.client W/GRYL: onDestroy()
10-21 15:42:57.709 6821-20260/gryl.client I/GRYL: 999

说明停止并销毁了当前启动的service.

若未调用stopService或stopSelf,按返回键后销毁当前Activity后,Log依然打印

10-21 15:42:49.707 6821-20260/gryl.client I/GRYL: 999

说明Service一直在后台运行,没有销毁。

需要注意的是:(a)如果service没有被创建,当调用startService后会执行onCreate回调,service创建后没有被销毁onDestroy,会一直运行,多次调用startService也不会反复的执行onCreate回调,因此在这个回调函数中可以执行一些初始化的工作。

(b)多次执行startService方法,onStartCommand方法会相应的被多次调用。在onStartCommand中可根据传入的Intent参数执行一些工作。

(2)通过BindService来启动Service

Log:

10-21 15:56:15.737 22681-22681/gryl.client W/GRYL: onCreate()
10-21 15:56:15.738 22681-22681/gryl.client W/GRYL: onBind
10-21 15:56:16.739 22681-1908/gryl.client I/GRYL: 999
10-21 15:56:17.740 22681-1908/gryl.client I/GRYL: 999
10-21 15:56:18.740 22681-1908/gryl.client I/GRYL: 999
10-21 15:56:19.741 22681-1908/gryl.client I/GRYL: 999
10-21 15:56:20.229 22681-22681/gryl.client W/GRYL: onUnbind
10-21 15:56:20.229 22681-22681/gryl.client W/GRYL: onDestroy()
10-21 15:56:20.741 22681-1908/gryl.client I/GRYL: 999

我个人对这种方式的理解是这样的:(a)service与启动它的组件如Activity是关联的,和Activity的生命周期相关联的。当Activity被销毁onDestroy时,Service与之绑定的Activity会解除绑定关系。

MainActivity执行BindService后,按Back键后打印的Log:

10-21 16:05:02.340 10760-10760/gryl.client W/GRYL: MyService: onCreate()
10-21 16:05:02.342 10760-10760/gryl.client W/GRYL: MyService: onBind
10-21 16:05:03.345 10760-10890/gryl.client I/GRYL: 999
10-21 16:05:04.345 10760-10890/gryl.client I/GRYL: 999
10-21 16:05:05.346 10760-10890/gryl.client I/GRYL: 999
10-21 16:05:06.346 10760-10890/gryl.client I/GRYL: 999
10-21 16:05:07.178 10760-10760/gryl.client W/GRYL: MainActivity:  onDestroy()
10-21 16:05:07.182 10760-10760/gryl.client W/GRYL: MyService: onUnbind
10-21 16:05:07.182 10760-10760/gryl.client W/GRYL: MyService: onDestroy()
10-21 16:05:07.347 10760-10890/gryl.client I/GRYL: 999

当然可以调用unbindService解除绑定关系。Log:

10-21 16:08:19.976 10760-10760/gryl.client W/GRYL: MyService: onCreate()
10-21 16:08:19.976 10760-10760/gryl.client W/GRYL: MyService: onBind
10-21 16:08:20.978 10760-14105/gryl.client I/GRYL: 999
10-21 16:08:21.979 10760-14105/gryl.client I/GRYL: 999
10-21 16:08:22.979 10760-14105/gryl.client I/GRYL: 999
10-21 16:08:23.498 10760-10760/gryl.client W/GRYL: MyService: onUnbind
10-21 16:08:23.498 10760-10760/gryl.client W/GRYL: MyService: onDestroy()
10-21 16:08:23.980 10760-14105/gryl.client I/GRYL: 999

(b)可通过IBinder接口获取Service的实例,从而可实现在Activity中直接调用Service中的各种方法,实现Activity与Service的各种交互,而这是startService无法做到的。

如本文中在MyService的OnBind中执行了

public IBinder onBind(Intent intent) {
    Log.w(getClass().getSimpleName()+": onBind");
    return new MyBinder();
}
public class MyBinder extends Binder {

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

    public void setData(String s) {
        mStr = s;
    }
}

在MainActivity中implements ServiceConnection:

private class MyServiceConnection implements ServiceConnection {

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        myBinder = (MyService.MyBinder) service;
        myService = myBinder.getMyService();
        myService.setCallback(new MyService.Callback() {
            @Override
            public void receive(String rec) {
                Message msg = new Message();
                Bundle bundle = new Bundle();
                bundle.putString("data", rec);
                msg.setData(bundle);
                mHandler.sendMessage(msg);
            }
        });
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        myBinder = null;
    }

    @Override
    public void onBindingDied(ComponentName name) {

    }
}

获取到Service实例,这样的话就实现了再Activity中通过Service实例调用Service中设计的各种方法了。

好了,就到这,可能表述的不是特别准确。

 

你可能感兴趣的:(Android)