和大家熟悉的Activity组件一样,service也是Android应用开程序发中常用的组件,它和acitivy一样也有自己的生命周期,不同的是service是运行在后台的,没有同用户直接交互的界面。
service的是有两种启动方式:
第一种是通过startservice方式来启动,通过此方式来启动的service会一直运行在后台,除非调用者主动停止服务或者是系统异常杀死。 此过程对应的生命周期是:
onCreate()----onStartCommand()-----onStop()----onDestory()
当调用者通过其他组件来调用一次startService之后,首先触发onCreate(),然后是调触发onStartCommand()
调用者停止服务后 触发onStop和onDestory
这个过程中,无论startSrvice被调用多少次,onCreate只会执行一次,但是onStartCommand会执行多次,直到有人停止service触发了onStop和onDestory。service才会重走生命周期
下面重点说一下onStartCommand()这个方法,这个函数有一个int的返回值,根据不同的返回值对应不同的情况:
START_STICKY
如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY
“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
START_REDELIVER_INTENT
重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
START_STICKY_COMPATIBILITY
START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
当调用者在外部通过stopService()或者在service内部通过StopSelf()方式停止了service,这个时候service是不回自动重启。
所以为了程序的性能,我们在掉用了startService之后,一定要记得stopService,以免引起不可预知的错误。
第二种是通过bindService方式来启动,通过此方式来启动的service会和调用者的生命周期绑定,调用者被销毁的时候,service也会被销毁, 此过程对应的生命周期是:
onCreate()----onBind()-----onUnbind()----onStop()----onDestory()
当调用者通过其他组件来调用一次bindService之后,首先触发onCreate(),然后是调触发onBind()
调用者解除绑定后 触发onUnbind--onStop和onDestory
这个过程中,无论bindService被调用多少次,onCreate只会执行一次,同样onBind()也只会执行一次,直到有人解除绑定service触发了onUnbind,直到onDestory。service才会重走生命周期,具体调用方式如下:
以在activity中绑定service为例
Intent mIntent = new Intent(context, GlassService.class);
bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mGlassService = ((GlassService.MyBinder) iBinder).getGlassService();
if (mGlassService != null) {
......
......
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
.......
......
}
};
注意此处有坑,当我们使用同一个context和serviceconnection去执行bindservice时,onServiceConnected方法只会被回调一次,除非我们传入不同的context和serviceconnection去调用bindService才会去触发onServiceConected回调。因为onBind方法是返回的IBinder对象是通过onServiceConnected会来回调给调用者,当serviceConnection对象不变时,此回调是不会多次调用的
,所以这个时候可以设置一个flag标志位,来判断是否需要多次bindService,在上面代码的基础上改动如下:
if (isRegist) {
if (mGlassService != null) {
mGlassService.setIStausCallback(iStausCallback);
mGlassService.connectWifi();
}
} else {
Intent mIntent = new Intent(context, GlassService.class);
this.iStausCallback = iStausCallback;
context.bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
isRegist = true;
mGlassService = ((GlassService.MyBinder) iBinder).getGlassService();
if (mGlassService != null) {
mGlassService.setIStausCallback(iStausCallback);
mGlassService.connectWifi();
mGlassService.setReleaseListener(GlassServiceState.this);
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
isRegist = false;
}
};
所以当我们通过bindService启动service之后,一定要记得调用onUnbind方法来解除绑定,这样才能保证onServiceConnected回调能正常执行。
当然这两种方式我们可以结合者使用:
当程序先通过bindservice调用之后,再通过startService调用。onCreate方法也只会执行一次。
这个时候如果调用unUnbind方法,service并不会被销毁,也就说不会执行onDestory方法,直到用户调用了StopService之后,Servie才会被销毁。
当程序先通过StartService调用之后,再通过bindservice调用。onCreate方法也只会执行一次。
这个时候如果调用了StopService,service也不会被销毁,直到用户调用onUnbind方法,service才会被销毁.。
总结:当我们只是单纯的想启动一个服务在后台执行任务,无需和调用者进行数据交互,可以使用StartService方式
当想使用Service内部定义的功能的时候,也就是说需要和Service有交互的时候,可以使用bindService方式来使用。
也可以两种方式结合来使用。