Android源码系列(14) -- IntentService

Posted by phantomVK on October 14, 2018

一、类签名

IntentService 是异步处理 IntentService 抽象子类。客户端通过 startService(Intent) 发送请求,服务根据需要启动,轮流处理收到的 Intent ,所有任务处理完后服务自行结束。

public abstract class IntentService extends Service

这种 “工作队列处理器” 模式主要适用于从应用主线程转移任务。 IntentService 是简化这种模式和关注处理者的类,只需继承此类并实现 onHandleIntent(Intent)IntentService 会接收Intent,启动工作线程进行处理,并在适当时候关闭Service(没有任务时)。

所有工作由子线程串行处理,不会阻塞主线程。处理逻辑需要实现抽象方法 onHandleIntent 实现。源码来自Android 28

二、数据成员

线程包含的Looper

private volatile Looper mServiceLooper;

使用Looper的Handler

private volatile ServiceHandler mServiceHandler;

工作线程名称

private String mName;

重分发标志位

private boolean mRedelivery;

三、内部类

ServiceHandler

绑定到 LooperHandler 是一个静态内部类。 轮到对应 Intent 处理时,实例送到 handleMessage(Message msg) 并调用 onHandleIntent()

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 实例,由子类构造方法调用

// @param name 为工作线程指定名称,主要方便Debug
public IntentService(String name) {
    super();
    mName = name;
}

五、成员方法

enabledtrueonStartCommand(Intent, int, int) 返回 Service.START_REDELIVER_INTENT。当 onHandleIntent(Intent) 结束前服务死亡,服务会重启并重分发最近的 Intent。 若 enabledfalse,服务死亡时销毁所有 Intent

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

创建 HandlerThreadServiceHandler

@Override
public void onCreate() {
    super.onCreate();
    
    // 创建并启动HandlerThread,实例内部启动Looper
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();

    // 从HandlerThread获取Looper
    mServiceLooper = thread.getLooper();
    // 从Looper构建Handler
    mServiceHandler = new ServiceHandler(mServiceLooper);
}

ServicestartService() 触发时回调 onStartCommand() 调用 onStart() 。不应重写此方法,如有必要请重写 onHandleIntent

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

此方法封装目标 IntentMessage ,送入 Handler 的消息队列等待分发,处理顺序是FIFO。

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

Service 销毁时调用 Looper.quit() ,此方法内部调用 MessageQueue.quit(false) 关闭消息队列。

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

onBind(Intent intent) 默认返回null。若需支持 bindService() 需重写。

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

分派任务时调用此方法,需在子类实现。每次只有一个 Intent 执行,执行独立于应用其他工作线程。运行任务需较长时间会阻塞相同 IntentService 的其他请求,但不会阻塞其他线程。

所有请求完成处理后 IntentService 自动结束运行,无需主动调用 stopSelf 方法。

@WorkerThread
// @param intent 传递给Context#startService(Intent)的实例
protected abstract void onHandleIntent(@Nullable Intent intent);

六、自动结束

执行流程(1/2):

  • 假设 IntentService 实现类为 WorkerService,通过 Intent 首次发起任务;
  • WorkerService 收起启动进入 onCreate() 初始化;
  • onStartCommand() 接收 Intent 同时,还能收到配对 startId
  • onStart() 方法内:IntentstartId 构造为 Message,放入消息队列等待处理;
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    // 构造消息
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

执行流程(2/2):

  • ServiceHandler 任务完成后,从 Message 取出 startId 去调用 Service.stopSelf(int)
  • 系统知道之前传给 WorkerServiceIntent 已经执行完毕;
  • 若还有 startIdIntent 没有调用 stopSelfWorkerService 持续运行直至所有任务完成
private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        // 执行取出的任务
        onHandleIntent((Intent)msg.obj);
        // 调用Service.stopSelf(int)
        stopSelf(msg.arg1);
    }
}

七、相关链接