文中的源代码版本为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
.