Android进阶9:IntentService的妙用

2,301 阅读7分钟

原来模式

我们知道Service是运行在主线程里的,因此,如果在服务里面执行耗时代码操作,我们需要开启一个子线程去处理这些代码。比如我们可以在onStartCommand方法里面去开启子线程来处理耗时代码。

public int onStartCommand(Intent intent, int flags, int startId) {
         Thread thread = new Thread(){
            @Override
            public void run() {
                /**
                 * 耗时的代码在子线程里面写
                 */

            }
          };
        thread.start();
        return super.onStartCommand(intent, flags, startId);
    }

但是,我们都知道,服务一旦启动,就会一直运行下去,必须调用stopService()或者stopSelf()方法才能让服务停止下来。所以,我们来修改一下run方法

public void run() {
         /**
           * 耗时的代码在子线程里面写
           */

        stopSelf();

     }
    }

就这样,我们很容易的就在服务里面开启了一个线程,然后在代码最后面加上stopSelf();这样就可以在代码运行结束的时候,结束服务了。但是这样对于我们开发者来说,是不是有些麻烦呢,确实有点麻烦,比如你有时候忘记了开启线程呢?或者忘记了调用stopSelf()?

所以,谷歌给我们一个很好的类,通过这个类我们就可以不用管这些东西,因为这个类已经帮我们实现了在子线程中操作代码了。同时,但子线程代码执行完毕,这个服务会自动销毁,不用再占用内存资源。所以,我们通过这个类,就可以不用去开启线程,也不用去销毁这个服务。因为,这个类都帮我们处理好了。这个类就是IntentService。这个类的使用和Service大同小异,但是比Service更加省心,更加方便。下面我们直接看代码吧,我习惯在代码中讲解。

IntentService源码

/**
 * IntentService是一个以{@linkService}的为基类来处理异步请求的类
 * 客户端发送请求通过{@link android.content.Context *#startService(Intent)}调用;
 * 该服务根据需要启动,使用worker线程依次处理每个Intent线程,并在run工作完成时自行停止本service。
 *
 * <p>这种“工作队列处理器”模式通常用于卸载任务
 *来自应用程序的主线程。 IntentService类存在于
 *简化这种模式并处理机制。要使用它,请扩展
 * IntentService并实现{@link #onHandleIntent(Intent)}。 IntentService
 * 将接收Intents,启动工作线程,并停止服务
 *合适。
 *
 * <p>所有请求都在一个工作线程上处理 - 它们可以作为
 *尽可能长(并且不会阻止应用程序的主循环),但是
 *一次只能处理一个请求。
 *
 */

public abstract class IntentService extends Service {

    //开启线程的Looper
    private volatile Looper mServiceLooper;
    //用于发送和处理消息的handler
    private volatile ServiceHandler mServiceHandler;
    //子线程的名称
    private String mName;
    //是否可重复发送
    private boolean mRedelivery;


    //处理消息handler的实现
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            //子线程

            //抽象方法 留给子类去重写
            onHandleIntent((Intent)msg.obj);
            // 子线程任务执行完了,停止本service
            stopSelf(msg.arg1);
        }
    }

    /**
     * 构造函数
     * @param name worker线程的名字 对调试有用
     */

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

    /**
     * 
     * Sets intent redelivery preferences.  Usually called from the constructor
     * with your preferred semantics.
     * 设置intent重发偏好,通常在构造函数调用
     *
     *
     * 如果设置是true,{@link #onStartCommand(Intent, int, int)} 将返回{@link Service#START_REDELIVER_INTENT}
     * 因此,如果这个进程在onHandleIntent返回之前死掉了,那么进程将会被重启,并且发送此intent
     * 如果多个intents被发送,只有最近的一个会被确保重新发送
     *
     * 如果设置为false,{@link #onStartCommand(Intent, int, int)} 将返回{@link Service#START_NOT_STICKY}
     * 如果这个进程死掉了,那么这个intent就死掉了
     *
     */

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

    @Override
    public void onCreate() {

        super.onCreate();

        //使用HandlerThread开启一个线程,并产生looper和消息队列
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        //获取上述子线程的looper
        mServiceLooper = thread.getLooper();
        //初始化 handler
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        //onstart时发送一个消息给handle

        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }


    @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();
    }

    /**
     * Unless you provide binding for your service, you don't need to implement this
     * method, because the default implementation returns null. 
     * @see android.app.Service#onBind
     */

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

    /**

     * 这个方法在子线程中执行,一次只能执行一个事件,
     */

    @WorkerThread
    protected abstract void onHandleIntent(Intent intent);
}

总结:使用IntentServices是使用Service+ HandlerThread的方式,很多情况下我们可以使用HandlerThread+ handler 来进行线程执行和handler分发消息。