ActivityとService間のデータ通信

10678 ワード

サービスを起動するには、ActivityでstartServiceまたはBindServiceメソッドを呼び出す2つの方法があることを知っています.
では、両者の違いは何でしょうか.コードで話しましょう.
 
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によるサービス開始
  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
現在起動しているサービスを停止して破棄することを説明します.
stopServiceまたはstopSelfが呼び出されていない場合、戻るキーを押して現在のActivityを破棄した後も、Logは印刷されます.
10-21 15:42:49.707 6821-20260/gryl.client I/GRYL: 999
サービスはバックグラウンドで実行され、破棄されていないことを示します.
(a)サービスが作成されていない場合、startServiceが呼び出された後にonCreateコールバックが実行され、サービスが作成された後にonDestroyが破棄されずに実行され、startServiceが複数回呼び出されてもonCreateコールバックが繰り返し実行されないため、このコールバック関数では初期化された作業をいくつか実行することができることに注意してください.
(b)startServiceメソッドを複数回実行すると、onStartCommandメソッドが複数回呼び出されます.onStartCommandでは、入力されたIntentパラメータに基づいていくつかの作業を実行できます.
(2)BindServiceによるサービス開始
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)サービスは、Activityのようなコンポーネントを起動することに関連し、Activityのライフサイクルに関連しています.ActivityがonDestroyを破棄すると、ServiceがバインドしたActivityはバインド関係を解除します.
MainActivity BindService実行後、Backキーを押して印刷するログ:
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インタフェースによってサービスのインスタンスを取得することができ、Activityでサービスを直接呼び出す様々な方法を実現することができ、Activityとサービスの様々なインタラクションを実現することができ、これは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) {

    }
}

サービスインスタンスを取得することで,サービスインスタンス呼び出しにおいて設計された様々な方法をActivityで実現する.
はい、これで、特に正確ではないかもしれません.