并发编程(7)Intentservice源码分析

244 阅读4分钟

概述

前面分析了HandlerThread源码,下面按照顺序分析IntentService的源码,IntentService是自己维护了一个线程,来执行耗时的操作,然后里面封装了HandlerThread,能够方便在子线程创建Handler。

正文

注释

IntentService is a base class for {@link Service}s that handle asynchronous
requests (expressed as {@link Intent}s) on demand.  Clients send requests
through {@link android.content.Context#startService(Intent)} calls; the
service is started as needed, handles each Intent in turn using a worker
thread, and stops itself when it runs out of work.

IntentService是继承自Service用来处理异步请求的一个基类,客户端startService发送请求,IntentService就被启动,然后会在一个工作线程中处理传递过来的Intent,当任务结束后就会自动停止服务。

This "work queue processor" pattern is commonly used to offload tasks
from an application's main thread.  The IntentService class exists to
simplify this pattern and take care of the mechanics.  To use it, extend
IntentService and implement {@link #onHandleIntent(Intent)}.  IntentService
will receive the Intents, launch a worker thread, and stop the service as appropriate

工作器处理模式通常用来加载应用主线程的耗时任务,IntentService用来简化这种模式并且专注于耗时任务的处理。使用IntentService,需要继承IntentService并且复写onHandleIntent方法。IntentService在接收到一系列Intent之后,启动一个子线程,然后合适的实际关闭Service。

All requests are handled on a single worker thread -- they may take as
  long as necessary (and will not block the application's main loop), but
  only one request will be processed at a time.

所有的请求都是都是在同一个子线程中进行处理的—他们可能会花费很长时间(并不会阻塞应用的loop线程),但是在同一时刻IntentService只能处理一个请求。

通过注释,已经将IntentService的使用方式,使用场景描述地相当清楚,不再多解释,相比较我们自己在Intent中开启线程处理耗时任务,IntentService不需要我们自己去关闭Service,它自己会在任务完成之后自行关闭,不过每次只能处理一个任务,所以不适用于高并发,适用于请求数较少的情况,类似于APP的版本检测更新,后台定位功能以及读取少量的IO操作。

成员变量

    private volatile Looper mServiceLooper;//子线程中的Looper
    private volatile ServiceHandler mServiceHandler;//内部持有的一个Handler
    private String mName;//内部创建的线程名字
    private boolean mRedelivery;//服务被异常终止后重新创建调用onStartCommand是否回传Intent

ServiceHandler

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

        @Override
        public void handleMessage(Message msg) {
          //子线程中回调Intent
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

内部创建了一个ServiceHandler,然后将传递过来的Intent封装成一个Message,然后再将Message封装成一个Intent,回调onHandleIntent,其实转换的目的就是讲主线程的Intent切换到子线程中去执行了而已。

构造方法

  //工作线程的名字
  public IntentService(String name) {
        super();
        mName = name;
    }

onCreate

    @Override
    public void onCreate() {
        super.onCreate();
        //创建HandlerThread	
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        //开启线程创建子线程Looper
        thread.start();
        //获取子线程Looper
        mServiceLooper = thread.getLooper();
       //创建子线程Handler
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

onStartCommand

  @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        //调用onStart方法
        onStart(intent, startId);
       //根据mRedelivery的值来确定返回重传Intent的黏性广播还是非黏性广播
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

onStart

  @Override
    public void onStart(@Nullable Intent intent, int startId) {
        //创建一个Message
        Message msg = mServiceHandler.obtainMessage();
      	//消息标志,作为当前Service的标志
        msg.arg1 = startId;
      	//携带Intent
        msg.obj = intent;
      	//发送消息,此时将线程切换到子线程
        mServiceHandler.sendMessage(msg);
    }


   @Override
        public void handleMessage(Message msg) {
            //处理发送过来的消息,在子线程
            onHandleIntent((Intent)msg.obj);
           //处理完消息之后停止Service
            stopSelf(msg.arg1);
        }

onDestroy

    @Override
    public void onDestroy() {
       //退出Looper
        mServiceLooper.quit();
    }

使用方式

IntentService intentService = new IntentService("main") {
    @Override
    protected void onHandleIntent(Intent intent) {
        // 处理耗时操作
    }
};
//不需要关注Service的生命周期,IntentService会自行处理

总结

IntentService实际上内部实例化了一个HandlerThread,并且封装了一个Handler,所以他的工作流程通过上面的源码,分析如下:

  1. 创建一个HandlerThread,开启HandlerThread来创建Looper
  2. 创建一个Handler,传入Looper,从而在子线程实例化Handler
  3. 在onStartCommand中获取到的Intent作为消息的obj发送出去
  4. 然后在onHandleIntent中处理这个消息,注意此时是在子线程
  5. 跟HandlerThread一样,IntentService内部是采用Handler来实现的,所以任务是串行执行的,不适用于大量耗时操作。