文中的源代码版本为api23
JobScheduler之超时检查
JobServiceContext
与JobService
交互的过程中会JobServiceContext
会进行超时检查,下面我们来看看超时检查是怎么做的。
我们需要解决的主要问题是:
- 哪些操作会执行超时检查
- 超时时间是多少
- 一旦发生超时
JobServiceContext
会怎么处理
哪些操作会执行超时检查
JobServiceContext
中使用一个名为scheduleOpTimeOut
的方法来执行超时检查,那么哪些地方会调用该方法呢?
通过全局搜索发现有以下调用点:
- 执行服务的
bind
操作时
boolean executeRunnableJob(JobStatus job) {
synchronized (mLock) {
//...
scheduleOpTimeOut();
final Intent intent = new Intent().setComponent(job.getServiceComponent());
boolean binding = mContext.bindServiceAsUser(intent, this,
Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,
new UserHandle(job.getUserId()));
//...
return true;
}
}
复制代码
- 触发
JobService.onStartJob
方法时
private void handleServiceBoundH() {
//...
try {
mVerb = VERB_STARTING;
scheduleOpTimeOut();
service.startJob(mParams);
} catch (RemoteException e) {
Slog.e(TAG, "Error sending onStart message to '" +
mRunningJob.getServiceComponent().getShortClassName() + "' ", e);
}
}
复制代码
- 等待
JobService
异步执行任务的期间
private void handleStartedH(boolean workOngoing) {
switch (mVerb) {
case VERB_STARTING:
mVerb = VERB_EXECUTING;
if (!workOngoing) {
// Job is finished already so fast-forward to handleFinished.
handleFinishedH(false);
return;
}
//...
//workOngoing为true表示JobService
//需要异步执行任务,完成任务后需要调用
//jobFinished方法通知JSC
scheduleOpTimeOut();
break;
default:
//...
return;
}
}
复制代码
- 停止
JobService
时
private void sendStopMessageH() {
removeOpTimeOut();
//...
try {
mVerb = VERB_STOPPING;
scheduleOpTimeOut();
service.stopJob(mParams);
} catch (RemoteException e) {
//...
}
}
复制代码
可以发现,JobService
在执行每一步操作的时候都会有超时检查。
超时时间是多少
这个问题就需要我们来看一下scheduleOpTimeOut
方法了
private void scheduleOpTimeOut() {
removeOpTimeOut();
//有两个事件
final long timeoutMillis = (mVerb == VERB_EXECUTING) ?
EXECUTING_TIMESLICE_MILLIS : OP_TIMEOUT_MILLIS;
//log...
Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT);
mCallbackHandler.sendMessageDelayed(m, timeoutMillis);
mTimeoutElapsed = SystemClock.elapsedRealtime() + timeoutMillis;
}
复制代码
EXECUTING_TIMESLICE_MILLIS
为10分钟,OP_TIMEOUT_MILLIS
为8秒
从代码中我们可以发现超时时间有两个,不同的操作有不同的超时时间
mVerb
为VERB_EXECUTING
的超时消息,只有在JobService
执行异步任务时才会触发,因此我们可以将超时简单的分为两种:
JobService
异步任务执行超时(10mins)- 跨进程调用超时(8s)
一旦发生超时JobServiceContext
会怎么处理
JobServiceContext
使用handleOpTimeoutH
方法来处理超时
private void handleOpTimeoutH() {
switch (mVerb) {
case VERB_BINDING:
//log...
closeAndCleanupJobH(false /* needsReschedule */);
break;
case VERB_STARTING:
//log...
closeAndCleanupJobH(false /* needsReschedule */);
break;
case VERB_STOPPING:
//log...
closeAndCleanupJobH(true /* needsReschedule */);
break;
case VERB_EXECUTING:
//log...
sendStopMessageH();
break;
default:
//log...
closeAndCleanupJobH(false /* needsReschedule */);
}
}
复制代码
主要处理方法有closeAndCleanupJobH
和sendStopMessageH
sendStopMessageH
该方法会立刻执行stopJob
方法,通知JobService
结束任务closeAndCleanupJobH
该方法会直接解绑JobService
,我们之前讲过了此处不再赘述。唯一一点是,如果是跨进程执行stopJob
方法超时的话,那么needsReschedule
参数就为true
。
总结
JobScheduler
在执行服务绑定、跨进程调用JobService.onStartJob
、JobService.onStopJob
以及JobService
异步执行任务期间都会进行超时检查JobService
异步执行超时时间为10mins,其他所有操作都是8sJobService
异步执行超时后JobServiceContext
会跨进程调用JobService.onStopJob
。其他操作超时,会调用closeAndCleanupJobH
直接解绑服务,如果是跨进程调用JobService.onStopJob
时超时,则还会重新执行Job
.