本篇文章主要是讲解一些关于Service的知识点。
Service的生命周期
Service有两种启动方式,startService
与bindService
。
首先来看startService
,通过该方式启动的Service与调用者没有任何关联,调用者也无法调用该Service中的任何方法。生命周期如下:
当第一次启动Service时会调用该Service的onCreate
方法,然后调用onStartcommand
,但当后面再次启动该Service且该Service还在运行中时,就会跳过onCreate
方法,直接执行onStartCommand
方法。
Service还可以通过bindService
来绑定Service。调用者绑定Service后,可以与该Service进行交互,但当调用者被销毁时也需要调用unBindService
来解绑,所以绑定可以理解为不同生但同死。生命周期如下:
只有当Service没有运行时才会调用onCreate
、onBind
这两个方法,如果Service正在运行的话,这两个方法均不会执行。
上面就是关于Service启动与Service绑定的生命周期介绍,其实一个Service可以同时调用startService
和bindService
。如果这样调用的话,结束的时候就必须同时停止和解绑Service。
关于Service生命周期的具体调用可以阅读Android源码之Service启动流程这篇文章。
Service类onStartCommand()返回值
通过startService
启动Service时会调用onStartCommand
这个方法,该方法有四种返回值,如下:
START_STICKY
:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。START_NOT_STICKY
:使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。START_REDELIVER_INTENT
:使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入,重启服务并不是立即执行的,被异常kill次数越多,重启花费时间越长。START_STICKY_COMPATIBILITY
:START_STICKY
的兼容版本,但不保证服务被kill后一定能重启,但重启后不会调用onStartCommand
这个方法。
系统默认返回值是START_STICKY
或START_STICKY_COMPATIBILITY
,所以使用Service时要注意onStartCommand
的返回值,避免异常kill掉导致程序崩溃。
关于Service的自启动流程可以阅读Android之Service自启动流程这篇文章
IntentService的使用
一般Service都是运行在主线程的,也就意味着无法再Service中做耗时操作,除非在Service中开启子线程,但这样的话就稍微麻烦一点了。于是谷歌就倒腾了IntentService
这个类,在IntentService
中能很方便的进行一些耗时操作且不用开发者自己管理Service和线程。下面就来看一下IntentService
的实现:
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
//执行耗时操作,如果执行完毕后没有新的Intent传递进来就会销毁当前Service
onHandleIntent((Intent)msg.obj);
//销毁当前Service
stopSelf(msg.arg1);
}
}
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
//创建一个HandlerThread,HandlerThread是Handler+Thread的实现
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
//开启子线程
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
//发生一条消息
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
//结束线程
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
//需要子类实现的方法,在该方法内可以执行耗时操作
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
上面就是HandlerService
的实现了,还是比较简单的,我们只管做自己的操作即可,Service及线程由IntentService
自己管理。
【参考资料】
【移动开发】Service类onStartCommand()返回值和参数
startService与bindService的区别