ActivityとService間のデータ通信
10678 ワード
サービスを起動するには、ActivityでstartServiceまたはBindServiceメソッドを呼び出す2つの方法があることを知っています.
では、両者の違いは何でしょうか.コードで話しましょう.
(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で実行したように
MainActivityでimplements ServiceConnection:
サービスインスタンスを取得することで,サービスインスタンス呼び出しにおいて設計された様々な方法をActivityで実現する.
はい、これで、特に正確ではないかもしれません.
では、両者の違いは何でしょうか.コードで話しましょう.
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で実現する.
はい、これで、特に正確ではないかもしれません.