Service在Android中和Activity是属于同一级别上的组件,我们可以将他们认为是两个好哥们,Activity仪表不凡,迷倒万千少女,经常做一些公众人物角色,而Service一副彪悍的长相,但却身强力壮,常常在后台做一些搬运工的力气活,虽然有些累,但大家都不能失去他。
下面我们就围绕Service对其进行全面讲解:
Service生命周期可以从两种启动Service的模式开始讲起,分别是context.startService()和context.bindService()。
(1)、startService的启动模式下的生命周期:
当我们首次使用startService启动一个服务时,系统会实例化一个Service实例,依次调用其onCreate和onStartCommand方法,然后进入运行状态,此后,如果再使用startService启动服务时,不再创建新的服务对象,系统会自动找到刚才创建的Service实例,调用其onStart方法;如果我们想要停掉一个服务,可使用stopService方法,此时onDestroy方法会被调用,需要注意的是,不管前面使用了多个次startService,只需一次stopService,即可停掉服务。
(2).bindService启动模式下的生命周期:
在这种模式下,当调用者首次使用bindService绑定一个服务时,系统会实例化一个Service实例,并一次调用其onCreate方法和onBind方法,然后调用者就可以和服务进行交互了,此后,如果再次使用bindService绑定服务,系统不会创建新的Service实例,也不会再调用onBind方法;如果我们需要解除与这个服务的绑定,可使用unbindService方法,此时onUnbind方法和onDestroy方法会被调用。
两种模式有以下几点不同之处:startService模式下调用者与服务无必然联系,即使调用者结束了自己的生命周期,只要没有使用stopService方法停止这个服务,服务仍会运行;通常情况下,bindService模式下服务是与调用者生死与共的,在绑定结束之后,一旦调用者被销毁,服务也就立即终止,就像江湖上的一句话:不求同生,但愿同死。
值得一提的是,以前我们在使用startService启动服务时都是习惯重写onStart方法,在Android2.0时系统引进了onStartCommand方法取代onStart方法,为了兼容以前的程序,在onStartCommand方法中其实调用了onStart方法,不过我们最好是重写onStartCommand方法。
MainActivity.java:
public class MainActivity extends Activity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private Button start;
private Button stop;
private Button bind;
private Button unbind;
private TextView textView;
private boolean binded;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binded = true;
Log.i(TAG, "onServiceConnected called.");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected called.");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
start = (Button) findViewById(R.id.bt_start);
stop = (Button) findViewById(R.id.bt_stop);
bind = (Button) findViewById(R.id.bt_bind);
unbind = (Button) findViewById(R.id.bt_unbind);
start.setOnClickListener(this);
stop.setOnClickListener(this);
bind.setOnClickListener(this);
unbind.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_start:
start();
break;
case R.id.bt_stop:
stop();
break;
case R.id.bt_bind:
bind();
break;
case R.id.bt_unbind:
unbind();
break;
}
}
/** * 启动服务 * * @param */
public void start() {
Intent intent = new Intent(this, MyService.class);
startService(intent);
textView.setText("服务运行中...");
}
/** * 停止服务 * * @param */
public void stop() {
Intent intent = new Intent(this, MyService.class);
stopService(intent);
textView.setText("服务已停止");
}
/** * 绑定服务 * * @param */
public void bind() {
Intent intent = new Intent(this, MyService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
/** * 解除绑定 * * @param */
public void unbind() {
if (binded) {
unbindService(conn);
binded = false;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbind();
}
}
MyService.java:
public class MyService extends Service {
private static final String TAG = "MyService";
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate called.");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand called.");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(TAG, "onStart called.");
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind called.");
return new Binder() {};
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind called.");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy called.");
}
}
一、startService()方式
2、当然我们觉得还不过瘾,再点击一次,我们会发现结果略有不同:
我们看到第二次点击时onCreate方法就不再被调用了,而是直接调用了onStartCommand方法(onStartCommand中又调用了onStart方法)。我们选择“Settings->Application s->Running services”就会发现我们刚刚启动的服务。
我们会发现onDestroy方法被调用了,此时服务就停止运行了。我们再次查看“Running services”,就会发现MyService这个服务已全无踪迹。
二、bindService()方式
注意:在使用bindService绑定服务时,我们需要一个ServiceConnection代表与服务的连接,它只有两个方法,onServiceConnected和onServiceDisconnected,前者是在操作者在连接一个服务成功时被调用,而后者是在服务崩溃或被杀死导致的连接中断时被调用,而如果我们自己解除绑定时则不会被调用,所以我们这里只研究onServiceConnected这个方法。
看样子是可以去绑定一个服务了,其实还不行,因为我们前面服务中的onBind方法返回值为null,这样是不行的,要想实现绑定操作,必须返回一个实现了IBinder接口类型的实例,该接口描述了与远程对象进行交互的抽象协议,有了它我们才能与服务进行交互。
1、点击一下绑定按钮:
onServiceConnected方法被调用了,证明绑定连接已经成功了。onCreate方法和onBind方法被调用了,此时服务已进入运行阶段,如果再次点击绑定按钮,onCreate和onBinder并不会再次被调用,这个过程中它们仅被调用一次。
2、点击解除绑定按钮:
可以看到onUnbind方法和onDestroy方法被调用了,此时MyService已被销毁,整个生命周期结束。
当我们退出MainActivity时,比如后退到主界面,onUnbind方法和onDestroy方法也会被调用,服务也会随之而结束,从这一点上看,MyService可以说是誓死追随着MainActivity。
三、startService和bindService同时使用
先启动后绑定:
2、再按下绑定服务的按钮:
此时,onCreate()方法不会重调,只有onBind被调用,两者就绑定成功。
3、再按下解除绑定的按钮:
此时,onUnbind方法方法被调用,注意,此时MyService并没有因解除绑定而终止,而是继续运行。
4、最后我们按下停止服务的按钮:
此时,onDestroy被调用了,此时MyService停止了运行,整个生命周期结束。
先绑定后启动:
2、再按下启动服务按钮:
此时,onCreate()方法不会重调,只有onStartCommand()和onStart()被调用。
3、再按下停止服务按钮:
按了好几次,发现没有日志输出,因为服务还处在绑定状态,无法停止服务。
总结:
由上可以看出,启动服务和绑定服务可以同时使用,不管哪个先执行,服务的onCreate()方法只会执行一次。 如果服务处于启动状态,单方面的解除绑定不会造成服务停止,同样,如果服务处于绑定状态,单方面的停止服务不会造成服务解除绑定。
以上就是关于MyService生命周期的讲解。
文章内容参考:http://blog.csdn.net/liuhe688/article/details/6874378
代码图片都是本人亲自实验抓取的。