Android源码系列(14) -- IntentService

Posted by phantomVK on October 14, 2018

一、类签名

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

1
public abstract class IntentService extends Service

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

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

二、数据成员

线程包含的Looper

1
private volatile Looper mServiceLooper;

使用Looper的Handler

1
private volatile ServiceHandler mServiceHandler;

工作线程名称

1
private String mName;

重分发标志位

1
private boolean mRedelivery;

三、内部类

ServiceHandler

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

1
2
3
4
5
6
7
8
9
10
11
12
private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        onHandleIntent((Intent)msg.obj);
        // msg.arg1是新建任务时传入的startId,方法内检查是否需要结束Service
        stopSelf(msg.arg1);
    }
}

四、构造方法

创建 IntentService 实例,由子类构造方法调用

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

五、成员方法

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

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

创建 HandlerThreadServiceHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
@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

1
2
3
4
5
@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。

1
2
3
4
5
6
7
@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) 关闭消息队列。

1
2
3
4
@Override
public void onDestroy() {
    mServiceLooper.quit();
}

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

1
2
3
4
5
@Override
@Nullable
public IBinder onBind(Intent intent) {
    return null;
}

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

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

1
2
3
@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,放入消息队列等待处理;
1
2
3
4
5
6
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    // 用传入参数构造Message,并加入到ServiceHandler的消息队列中
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

执行流程(2/2):

  • ServiceHandler 任务完成后,从 Message 取出 startId 去调用 Service.stopSelf(int)
  • 系统知道这个传给 WorkerServiceIntent 已经执行完毕;
  • 若还有其他 startIdIntent 没调用 stopSelfWorkerService 继续运行直至所有任务完成
1
2
3
4
5
6
7
8
9
10
11
12
13
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);
    }
}

七、相关链接