IntentService详解

来源:互联网 发布:app.js调用方法 编辑:程序博客网 时间:2024/06/16 02:24

  在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里面创建和管理线程。

0 0
原创粉丝点击