IntentService详解

       在Android开发中,我们通常会把耗时操作放到Service中处理,但是由于Service也是运行在主线程中的,所以在Service中直接处理耗时操作也是会导致ANR的。所以,我们一般需要在Service中另起线程去处理耗时操作。Android为我们提供了简单的机制去实现在Service中创建线程处理耗时任务,它就是IntentService。
  IntentService继承自Service,它内部封装了一个HandleThread去实现异步任务处理。通过startService提交任务,所有的任务串行执行,当所有任务都处理掉完毕后,service会自动停止,并不需要显示调用stopService。

IntentService的使用

  IntentService的使用需要创建一个子类去继承IntentService,并实现里面的抽象方法 onHandleIntent,在onHandleIntent方法中去处理耗时操作,下面我们来看一下IntentService的大致实现:
  

public class TestIntentService extends IntentService {
    public TestIntentService(String name) {
        super(name);
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        //do something
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

  使用IntentService我们不需要去创建线程去执行耗时任务,因为它的内部已经封装了一个HandleThread,它是一个带有Loop的thread,使用它可以轻松的去执行耗时的异步任务。同时,我们也不必去关心停止service的操作,因为IntentService默认会在所有任务处理完毕后去主动停止Service。下面我们从源码的角度来分析下IntentService的具体实现,这样就能更加清晰的了解IntentService所具有的特点。

IntentService的源码实现

  下面我们来看一下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) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

    public IntentService(String name) {
        super();
        mName = name;
    }


    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

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

    @Override
    public void onStart(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(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * This method is invoked on the worker thread with a request to process.
     * Only one Intent is processed at a time, but the processing happens on a
     * worker thread that runs independently from other application logic.
     * So, if this code takes a long time, it will hold up other requests to
     * the same IntentService, but it will not hold up anything else.
     * When all requests have been handled, the IntentService stops itself,
     * so you should not call {@link #stopSelf}.
     *
     * @param intent The value passed to {@link
     *               android.content.Context#startService(Intent)}.
     */
    @WorkerThread
    protected abstract void onHandleIntent(Intent intent);
}

  从onStartCommand和onHandleIntent方法的注释中,我们就很清楚的知道IntentService的使用,及其所具有的特性。下面我们来一步步来看这是如何实现的。
  IntentService本身也是一个Service,它具有Service的生命周期。我们先来看一下onCreate方法的实现,在onCreate方法中,创建一个HandleThread对象thread,这个thread将被用来执行耗时操作。同时用thread的Looper对象初始化了一个ServiceHandler对象mServiceHandler。ServiceHandler是IntentService的内部类,它继承自Handler,后面用到的时候我们再来分析它。至此,我们知道onCreate方法里就做了两件事,创建了一个HandleThread,以及和它关联的Handler对象。
  根据Service的生命周期,当有startService调用时,会回调onStartCommand方法。我们来看下onStartCommand方法的实现:

    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

  onStartCommand方法里面的逻辑很简单,在这个里面调用了onStart方法,它的返回值根据IntentService的成员变量mRedelivery 的值有两种情况,当mRedelivery 为true时返回START_REDELIVER_INTENT ,为false时返回的是START_NOT_STICKY。熟悉Service的同学应该知道,onStartCommand方法的返回值决定了当Service被系统kill掉的时候,service能否被自动重新创建。START_REDELIVER_INTENT 表明系统会自动重新创建该service,并会再次发送被kill之前的最后一个intent。START_NOT_STICKY表面系统不会自动重新创建该service。
  在IntentService中,mRedelivery 的默认值是false。它同时也提供了接口函数去改变mRedelivery 变量的值,这个方法就是setIntentRedelivery。前面我们提到了onStartCommand方法里面直接调用了onStart方法,下面我们来看下onStart方法:

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

  从代码可以看到,onStart方法的逻辑也很简单,就是通过我们在onCreate里面初始化的mServiceHandler去发送了一条消息。我们来看下ServiceHandler 的定义:

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

  我们知道mServiceHandler发送的消息会交给Handler的handleMessage去处理,而handleMessage会运行在handler looper所在的线程。在IntentService中,mServiceHandler的looper是在HnadlerThread中的,所以这个handleMessage会运行在HnadlerThread的线程中,这样就做到了IntentService去处理耗时操作而不用担心会阻塞主线程。
  在handleMessage中调用了onHandleIntent以及stopSelf方法,所以我们只需要把耗时操作写在onHandleIntent中去就可以了。同时,它自动调用了stopSelf方法,并传入对应的start id,这就解释了IntentService不需要我们手动显示调用stop方法,它会在处理完所有的intent之后自动停止。
  至此,我们就了解了IntentService的使用以及内在实现机制。它适用于处理串行耗时操作,对于需要并行处理的操作,就需要自己在Service里面创建和管理线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值