IntentService详解

IntentService是一种特殊的Service,它继承了Service并且它是一个抽象类,因此必须创建它的子类才能使用IntentService。IntentService可用于执行后台耗时任务,当任务执行后它会自动停止,同时由于IntentService是服务的原因,这导致它的优先级比单纯的线程要高很多,所以IntentService比较适合执行一些高优先级的后台任务,因为它优先级高不容易被系统杀死。在实现上,IntentService封装了Handler和HandlerThread,这一点可用从onCreate方法看出:

@Override
public void onCreate() {
    // TODO: It would be nice to have an option to hold a partial wakelock
    // during processing, and to have a static startService(Context, Intent)
    // method that would launch the service & hand off a wakelock.

    super.onCreate();
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();

    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
}

当IntentService第一次被启动时,它的onCreate方法会被调用,onCreate方法会创建一个HandlerThread,然后用它的Looper来构建一个Handler对象mServiceHandler,这样通过mServiceHandler发送的消息都会在HandlerThread中执行,从这个角度看,IntentService也可以用于执行后台任务,每次启动IntentService,它的onStartCommand都会被执行,IntentService在onStartCommand中处理每个后台任务的Intent。onStartCommand是如何执行的呢?

@Override
public void onStart(@Nullable Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

/**
 * You should not override this method for your IntentService. Instead,
 * override {@link #onHandleIntent}, which the system calls when the IntentService
 * receives a start request.
 * @see android.app.Service#onStartCommand
 */
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

onStartCommand中会调用onStart,IntentService仅仅是通过mServiceHandler发送了一个消息,这个消息会在HandlerThread中被处理,mServiceHandler收到消息后,会在onHandleIntent方法中处理。这个Intent和外界startService(intent)中的intent是完全一致的,通过对这个Intent的解析,就可以区分出具体的后台任务,这样在onHandleIntent中就可以对不同任务进行处理了。当onHandleIntent方法介绍后,会调用stopSelf(int startId)来尝试停止服务,这里不采用stopSelf()来停止服务,那是因为stopSelf()会立刻停止服务,而这个时候可能还有其他任务未处理,stopSelf(int startId)则会等待其他任务执行完毕后才终止服务。一般来说,stopSelf(int startId)在停止服务之前,会判断最近启动服务的次数是否和startId相等,如果相等则立即停止服务,不相等则不停止服务,这个策略可以从AMS的stopServiceToken方法的实现中找到依据。

IntentService中的onHandleIntent是个抽象方法,需要在子类中实现,它的作用是从Intent参数中区分具体的任务并执行这些任务。如果目前只存在一个后台任务,那么onHandleIntent方法执行完这个任务后,stopSelf(int startId)会直接停止服务;如果目前存在多个任务,当onHandleIntent方法执行完最后一个任务时,stopSelf(int startId)会立刻停止服务。由于每执行一个后台任务就必须启动一次IntentService,而IntentService内部则通过消息的方式向HandlerThread请求执行任务,Handler中的Looper是顺序处理消息的,这就意味着IntentService也是顺序执行后台任务的,当有多个后台任务同时存在时,这些后台任务会按照外界发起的顺序排队执行。

你可能感兴趣的:(Android)