IntentService是一种特殊的Service,他继承了Service并且它是一个抽象类,所以必须创建它的子类才能使用IntentService。IntentService可用于执行后台耗时任务,当任务执行完毕之后自动停止,由于IntentService是服务的原因,它的优先级要比单纯的线程要高,所以IntentService比较适合执行一些高优先级的任务,因为他优先级高,不容易被杀死。

从实现上来看,IntentService封装了HandlerThread和Handler。(HandlerThread是一个自带handler的线程,相比较于普通线程,完成了耗时操作使用主线程handler来通知主线程更新UI,HandlerThread需要别的线程使用它自带的handler来通知它执行任务。实现也非常简单,和上一篇handler机制中我们想要自定义一个子线程并且使用handler一样,只需要创建一个Loop,并启动它的消息循环即可,这里就不再展开了。)

@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方法会创建一个HandlerThread,然后利用它Loop来创建一个mServiceHandler,这样通过mServiceHandler发送的消息都会交给HandlerThread来处理。每次启动IntentService都会调用它的startCommand方法,startCommand调用onStart。

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


可以看到IntentService通过mServiceHandler发送了一条消息,这个消息会被HandlerThread处理,mServiceHandler收到消息后会将intent传给onHandleIntent方法处理。注意这个intent对象和外界startService传递的intent是一样的,通过这个intent可以解析出外界传递给IntetnService的参数,通过这些参数就可以区分具体的后台任务,onHandleIntent就可以进行针对性的处理。执行完毕后,IntentService会通过stopSelf(startId)来尝试停止服务,如果此时还有别的消息未处理,stopSelf(startId)会等待全部处理完毕再关闭。(通过判断最近启动服务次数和startId是否相等)

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


IntentService中的onHandleIntent方法需要我们继承之后自己实现,它可以区分intent中的参数来执行具体任务。每启动一次IntentService就等同于内部向HandlerThread发送一次请求,而Handler中的Looper是顺序执行任务的,所以intentService也是顺序执行后台任务的。

实现Demo:

public class MyIntentService extends IntentService {
    private final static String TAG = "MyIntentService";

    public MyIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String action = intent.getStringExtra("task_action");
        Log.i(TAG, "receive task :" + action);
        SystemClock.sleep(3000);
        if ("com.example.servicetest.TASK1".equals(action)) {
            Log.i(TAG, "handle task :" + action);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestory");
    }
}


在onHandleIntent中睡眠3秒模拟耗时操作,然后区分"task_action"来执行具体任务。

主线程调用:

Intent service = new Intent(this, MyIntentService.class);
        service.putExtra("task_action", "com.example.servicetest.TASK1");
        startService(service);
        service.putExtra("task_action", "com.example.servicetest.TASK2");
        startService(service);
        service.putExtra("task_action", "com.example.servicetest.TASK3");
        startService(service);




要注意在AndroidManifest中注册service。

Log:

09-19 01:57:00.403 4472-4492/com.example.servicetest I/MyIntentService: receive task :com.example.servicetest.TASK1
09-19 01:57:03.414 4472-4492/com.example.servicetest I/MyIntentService: handle task :com.example.servicetest.TASK1
09-19 01:57:03.414 4472-4492/com.example.servicetest I/MyIntentService: receive task :com.example.servicetest.TASK2
09-19 01:57:06.424 4472-4492/com.example.servicetest I/MyIntentService: receive task :com.example.servicetest.TASK3
09-19 01:57:09.434 4472-4472/com.example.servicetest I/MyIntentService: onDestory




综上,IntentService是一个适合执行后台耗时操作的Service,自带消息循环机制,采用顺序的方式执行任务,可以启动多次,完成任务后自动停止。