JobScheduler
JobScheduler是Android L(API21)新增的特性,用于定义满足某些条件下执行的任务。它的宗旨是把一些不是特别紧急的任务放到更合适的时机批量处理,这样可以有效的节省电量。
为什么需要JobScheduler
Android在进入待机状态时,会不断关闭各种硬件来延长手机的待机时间,首先屏幕会逐渐变暗直至关闭,然后CPU进入睡眠,这一切操作都是为了节约宝贵的电量资源。但是即使在这种睡眠状态下,大多数应用还是会尝试进行工作,他们将不断的唤醒手机。
在Android性能优化的电量篇中通过Battery Historian查看手机的耗电状况,可以知道Android的在蜂窝数据下电量消耗呈现间隔小,又频繁断断续续的出现,说明电量消耗性能很不好:
在WiFi连接下,网络传输的电量消耗要比移动网络少很多,应该尽量减少移动网络下的数据传输,多在WiFi环境下传输数据。
如何把任务缓存起来,做到批量执行,就是Job Scheduler了,应用需要做的事情就是判断哪些任务是不紧急的,可以交给Job Scheduler来处理,Job Scheduler集中处理收到的任务,选择合适的时间,合适的网络,再一起进行执行。
输入法中通知中心中的很多任务可以放到JobScheduler来,该API在21中引入,目前输入法的minSDK为14。
怎么使用JobScheduler
使用起来很简单,核心就是自己定义一个JobService(该service运行在主线程),在onStartJob中完成具体的业务逻辑,然后构建JobInfo来设定一些运行的场景和条件,最后放到系统服务JobScheduler中去,系统在指定的场景就会触发service。
-
创建JobService
public class JobSchedulerService extends JobService { @Override public boolean onStartJob(JobParameters params) { return false; } @Override public boolean onStopJob(JobParameters params) { return false; } }
我们创建一个继承自JobService且名字为JobSchedulerService的类,这个类必须实现两个方法,分别是onStartJob和 onStopJob,当任务开始时会执行onStartJob方法,因为这是系统用来触发已经被执行的任务。正如你所看到的,这个方法返回一个boolean值。如果返回值是false,系统假设这个方法返回时任务已经执行完毕。如果返回值是true,那么系统假定这个任务正要被执行,执行任务的重担就落在了你的肩上。当任务执行完毕时你需要调用jobFinished来通知系统。
当系统接收到一个取消请求时,系统会调用onStopJob方法取消正在等待执行的任务。
其实onStopJob在jobFinished正常调用结束一个job时,也是不会调用的,只有在该job没有被执行完,就被cancel掉的时候回调到,比如某个job还没有执行就被JobScheduler给Cancel掉时,或者在某个运行条件不满足时,比如原来在Wifi环境允许的某个任务,执行过程中切换到了非Wifi场景,那也会调用该方法。改方法也返回一个boolean值,返回true表示会重新放到JobScheduler里reScheduler,false表示直接忽略。
- 设置执行条件
想创建定时任务时,你可以使用JobInfo.Builder来构建一个JobInfo对象,然后传递给你的Service。JobInfo.Builder接收两个参数,第一个参数是你要运行的任务的标识符,第二个是这个Service组件的类名。
JobInfo.Builder builder = new JobInfo.Builder(i, mServiceComponent)
.setMinimumLatency(2000) // 设置任务允许最少延迟时间
.setOverrideDeadline(50000) // 设置deadline,若到期还没有到达规定的条件也会执行
.setRequireNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) //设置网络条件,非蜂窝数据的
.setRequiresCharging(true) // 设置充电条件
.setRequiresDeviceIdle(false) // 设置手机是否idle状态
.build();
其他设置方法 :
setMinimumLatency(long minLatencyMillis):
这个函数能让你设置任务的延迟执行时间(单位是毫秒),这个函数与setPeriodic(long time)方法不兼容,如果这两个方法同时调用了就会引起异常;setOverrideDeadline(long maxExecutionDelayMillis):
这个方法让你可以设置任务最晚的延迟时间。如果到了规定的时间时其他条件还未满足,你的任务也会被启动。与setMinimumLatency(long time)一样,这个方法也会与setPeriodic(long time),同时调用这两个方法会引发异常。setPersisted(boolean isPersisted):
这个方法告诉系统当你的设备重启之后你的任务是否还要继续执行。setRequiredNetworkType(int networkType):
这个方法让你这个任务只有在满足指定的网络条件时才会被执行。默认条件是JobInfo.NETWORK_TYPE_NONE,这意味着不管是否有网络这个任务都会被执行。另外两个可选类型,一种是JobInfo.NETWORK_TYPE_ANY,它表明需要任意一种网络才使得任务可以执行。另一种是JobInfo.NETWORK_TYPE_UNMETERED,它表示设备不是蜂窝网络( 比如在WIFI连接时 )时任务才会被执行。setRequiresCharging(boolean requiresCharging):
这个方法告诉你的应用,只有当设备在充电时这个任务才会被执行。-
setRequiresDeviceIdle(boolean requiresDeviceIdle):
这个方法告诉你的任务只有当用户没有在使用该设备且有一段时间没有使用时才会启动该任务。需要注意的是setRequiredNetworkType, setRequiresCharging 和 setRequiresDeviceIdle这几个方法可能会使得你的任务无法执行,除非调用setOverrideDeadline(long time)设置了最大延迟时间,使得你的任务在为满足条件的情况下也会被执行。
-
创建JobScheduler对象,并把JobInfo交给它管理
mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); xxxxxxx if(mJobScheduler.schedule(builder.build()) <= 0 ) { // if something goes wrong }
JobScheduler是个系统Service,我们的将自己的JobInfo传给它,由系统负责调用,其中这个schedule方法会返回一个整型。如果schedule方法失败了,它会返回一个小于0的错误码。否则它会我们在JobInfo.Builder中定义的标识id。
如果你的应用想停止某个任务,你可以调用JobScheduler对象的cancel(int jobId)来实现;如果你想取消所有的任务,你可以调用JobScheduler对象的cancelAll()来实现。