Service的生命周期
Service的分类
1、本地服务Local Service:
Local Service 用于应用程序内部。用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好
2、远程服务Remote Service:
Remote Service 用于android系统内部的应用程序之间。可以定义接口并把接口暴露出来,以便其他应用进行操作。可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。
Service的两种启动方式
1、startService方式(和stopService配对使用):
这种方式启动服务之后,调用者和服务就没有什么关系了,就算是退出当前的调用者,服务也不会关闭直到显式的调用stopService()或者stopSelf(),调用者和服务之间没有通信,这种方式服务的生命周期如下:
- onCreate() : 创建服务,并初始化一些资源
- onStartCommand() : 启动服务,值得说明的是服务中有onSart()方法,它是在android2.0一下的版本中使用。而在android2.0以上则使用onstartCommand()方法。它们两个方法放在一起使用时,不会产生冲突,同时每一次调用startService()都会调用onStartCommand()方法,但是实际上的每个服务都只会存在一个实例
- onDestory() : 销毁服务,并做资源回收
2、bindService方式(和unBindService配对使用):
这种方式启动服务之后,服务和调用者之间产生紧密的联系,当调用者销毁之后,服务也随之销毁,而且两者之间可以自由的通信,其生命周期如下
- onCreate() : 创建服务,并初始化一些资源
- onBind() : 绑定服务,服务开始运行
- onUnbind():取消绑定
- onDestroy() :销毁服务,并做资源回收
bindService方式调用的流程图:
注意:
1、使用bindService方法绑定服务时不会再走onStart()或者onStartCommand()方法,若是同时调用startService()和bindService()方法,那么在销毁的时候必须对应的执行stopService()和unBindService()方法才能销毁服务
2、ServiceConnection中的onServiceDisconnected()方法在正常情况下是不被调用的,它的调用时机是当Service服务被意外销毁时,例如内存的资源不足时
onStartCommand()方法返回值的探讨
- START_STICKY(常量值:1):sticky的意思是“粘性的”。使用这个返回值时,我们启动的服务跟应用程序”粘”在一起,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务。当再次启动服务时,传入的第一个参数将为null;
- START_NOT_STICKY(常量值:2):“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务
- START_REDELIVER_INTENT(常量值:3):重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入
以上三种情况,可以理解为发生车祸后的人:
- START_STICKY:(常量值:1)车祸后自己苏醒,但是失忆;
- START_NOT_STICKY:(常量值:2)车祸后再也没有苏醒;
- START_REDELIVER_INTENT:(常量值:3)车祸后自己苏醒,依然保持记忆。
关于IntentService
为什么要使用IntentService?
我们知道Service中的代码都是默认运行在UI线程中的,所以这里是不能直接处理一些耗时的逻辑,否则就容易出现ANR,这时候就需要使用Android多线程技术了,在每一个服务中的具体方法里开启一个子线程,在子线程中处理耗时的操作,如下所示:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
//......耗时操作
//处理完成之后,为防止服务一直运行,调用stopSelf方法
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
但是我们很容易忘记开线程或者是调用stopSelf()方法,因此可以使用Android中提供的IntentService类,用法如下:
public class MyIntentService extends IntentService {
//提供无参构造,必须调用父类的构造方法
public MyIntentService() {
super("MyIntentService");
}
//子类实现onHandleIntent,此方法运行在子线程中
@Override
protected void onHandleIntent(@Nullable Intent intent) {
//逻辑操作
}
@Override
public void onDestroy() {
super.onDestroy();
//销毁服务,回收资源
}
}
IntentService与activity的通信方式
使用Service和activity通信,其方式有两种,其一是使用绑定Binder的方式,其二是使用广播的方式,在IntentService中固然可以使用bindService开启服务,采用绑定Binder对象,但是这种方式不会执行onHandleIntent方法,我们知道IntentService是继承Service的一个抽象类,则使用bindService方式其实是和使用Service是一样的,这就失去了IntentService的意义了,因此可以采用第二种方式,就是广播的方式。我们从IntentService的源码就可以看到IntentService是不支持bindService这种方式的
/**
IntentService中没有继承Binder的类,并且onBind方法中返回值为“null”
*/
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
/**
采用startService会执行onStart方法,我们可以看到IntentService中有定义的Hander对象,发送消息
*/
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
/**
handleMessage方法中处理消息,之后执行stopSelf,这就是IntentService任务执行完成之后,
自动结束服务的原理
*/
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}