我们知道启动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<T extends HandlerCallback> extends Handler { private WeakReference<T> mWeakReference; public NoLeakHandler(T t) { mWeakReference = new WeakReference<T>(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中设计的各种方法了。
好了,就到这,可能表述的不是特别准确。