我们知道启动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 NoLeakHandlerextends 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中设计的各种方法了。
好了,就到这,可能表述的不是特别准确。