JobScheduler学习 附官方demo
后台任务是应用开发中常见的问题。
最简单的做法就是直接开一个Thread,用Handler通信即可,但是所开的线程和活动是没有关系的,一旦应用被杀死,就和之前所创建的线程失去了联系,就算活动再次启动,此时启动的线程并不是之前的线程。
当然,这个问题可以用Service解决,那么如果用户把服务也杀了呢?你可能会想用AlarmManager,周期性地进行唤醒,可是用户关机了,AlarmManager也就没了。当然这还没到“穷途末路”,用BroadcastReceiver就可以直接解决服务自启的所有问题。
但是让我们换个角度来看,打开管理器查看当前活动的服务就能看到,这些一直在活动的后台往往是导致手机耗电飞快的原因。当然这种问题是需要开发者的自觉的,如果让开发者来考虑省电,这将会是开发者的一大烦恼,比如说希望连接WiFi时才进行,插入充电器才进行,将会使代码大大增加;另一方面,万一此时没有网络可用呢?还得写一个BroadcastReceiver来监听网络情况。超级麻烦的不是吗?
Android L开始引入了一个新的API:JobScheduler。正如其名,它允许将任务调度直接交给系统,并且你所需要的许多约束条件,如周期调度,延迟调度,网络连接,电源插入,还有android L引入的空闲模式(虽然现在还挺鸡肋),都可以快捷地进行设置。现在就开始对JobScheduler的学习
API成员
JobInfo
代表一个任务,使用建造者模式进行制造,然后传递给JobScheduler进行调度管理。需要注意的是JobInfo类中的几个常量,建造时需要用到,至于作用会在后面的set方法中介绍:- BACKOFF_POLICY_EXPONENTIAL
- BACKOFF_POLICY_LINEAR
- DEFAULT_INITIAL_BACKOFF_MILLIS
- MAX_BACKOFF_DELAY_MILLIS
- NETWORK_TYPE_ANY
- NETWORK_TYPE_NONE
- NETWORK_TYPE_NOT_ROAMING
- NETWORK_TYPE_UNMETERED
JobInfo.Builder
JobInfo的建造者,其构造器为:
JobInfo.Builder(int jobId, ComponentName jobService)
- 1
- 1
第一个参数为该任务的标识符,该标识符在相同的uid的所有客户端中必须是唯一的(官方文档是这么写的,我的理解是在该设备上必须是唯一的)。为了保证在应用升级后也是稳定的,因此建议不要基于资源id进行设置
第二个参数是你希望用来处理该任务的服务对应的ComponentName,用来启动该服务
接下来是用来建造JobInfo的各个参数对应的set方法:
setBackoffCriteria(long initialBackoffMillis, int backoffPolicy)
设置退避/重试策略。类似网络原理中的冲突退避,当一个任务的调度失败时需要重试,所采取的策略。第一个参数时第一次尝试重试的等待间隔,单位为毫秒,预设的参数有:- DEFAULT_INITIAL_BACKOFF_MILLIS
30000 - MAX_BACKOFF_DELAY_MILLIS
18000000
第二个参数是对应的退避策略,预设的参数有:
- BACKOFF_POLICY_EXPONENTIAL
二进制退避。等待间隔呈指数增长 - BACKOFF_POLICY_LINEAR
- DEFAULT_INITIAL_BACKOFF_MILLIS
setMinimumLatency(long minLatencyMillis)
设置任务执行延迟的时长- setOverrideDeadline(long maxExecutionDelayMillis)
设置任务的最大延迟时长。一旦达到该时间,无论条件是否满足,任务都会执行
由于设置延迟对周期性任务来说没有意义,因此在build()时会抛出IllegalArgumentException异常
setPeriodic (long intervalMillis)
设置周期。可以保证在每个间隔之间任务最多只执行一次setPeriodic (long intervalMillis, long flexMillis)
在周期末的一个flex长度的窗口,任务都有可能被执行setPersisted (boolean isPersisted)
设置设备重启后,这个任务是否还保留。需要RECEIVE_BOOT_COMPLETED权限setRequiredNetworkType (int networkType)
设置要求的网络,只有接入给定类型的网络才能执行,而且是必须要接入网络才能执行。预置的参数有:- NETWORK_TYPE_NONE
默认值。表示与网络状态无关 - NETWORK_TYPE_ANY
必须连接网络 - NETWORK_TYPE_NOT_ROAMING
必须连接非漫游的网络 - NETWORK_TYPE_UNMETERED
必须连接非计费的网络
- NETWORK_TYPE_NONE
setRequiresCharging (boolean requiresCharging)
设置是否需要充电器接入。默认falsesetRequiresDeviceIdle (boolean requiresDeviceIdle)
设置是否需要设备处于空闲状态。默认false
空闲状态指设置已经有一段时间没有被使用addTriggerContentUri (JobInfo.TriggerContentUri uri)
添加一个TriggerContentUri,该Uri将利用ContentObserver来监控一个Content Uri,当且仅当其发生变化时将触发任务的执行
这个功能不能和setPeriodic(long)或者setPersisted(boolean)一起使用, 因为这样是没有意义的,否则在build()时会抛出IllegalArgumentException异常
为了持续监控content的变化,你需要在最近的任务触发后再调度一个新的任务setTriggerContentMaxDelay (long durationMs)
设置从content变化到任务被执行,中间的最大延迟setTriggerContentUpdateDelay (long durationMs)
设置从content变化到任务被执行中间的延迟。如果在延迟期间content发生了变化,延迟会重新计算build()
创建对应的JobInfo
JobInfo.TriggerContentUri
保存了一项任务触发绑定的content uri信息
其构造器为:JobInfo.TriggerContentUri(Uri uri, int flags)
- 1
- 1
第一个参数是希望监控的content的Uri,第二个参数是标识符
JobParameters
当任务被调度,交由应用处理时提供的对象,包含了该任务的信息。无法自己创建JobParameter的实例
由于是用来提供任务信息的,所以基本都是get方法:- PersistableBundle getExtras()
- int getJobId()
- String getTriggeredContentAuthorities()
获得触发该任务的content authorities - Uri[] getTriggeredContentUris()
- boolean isOverrideDeadlineExpired()
判断该调度是否因为达到deadline了
JobScheduler
负责调度任务。一般调用schedule(JobInfo)方法将任务加入到调度队列中。JobScheduler无法自己创建,因为是系统级的服务,所以用Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)获得其实例int schedule(JobInfo)
将任务加入到调度队列中。将会返回一个结果- RESULT_SUCCESS
加入成功 - RESULT_FAILURE
不合法的参数将会导致失败,有可能是该任务的run-time太短(不是很懂),或者其指定的JobService无法解析
- RESULT_SUCCESS
cancel(int jobId)
取消对应ID的任务- cancelAll()
取消由这个包注册的所有任务 - List< JobInfo > getAllPendingJobs()
获得这个包注册的正在等待的任务 - JobInfo getPendingJob(int jobId)
获得指定的由该包注册的正在等待的任务
JobService
JobScheduler的回调入口。
由于需要应用来完成任务的执行,因此需要继承该类,重载其onStartJob(JobParameter)方法,进行任务的执行
建议使用Handler来完成任务执行的逻辑,以防阻塞未来的任务
在Manifest注册该Service时,要注意添加android.permission.BIND_JOB_SERVICE权限,否则会被系统忽略void jobFinished (JobParameters params, boolean needsReschedule)
当完成任务的执行时,调用该方法通知JobManager。该方法可以在任何线程调用
第一个参数是该任务对应的JobParameter,你会在onStartJob方法获得
第二个参数表示是否需要重新调度。退避机制会产生作用,也就是重调度的任务加入到队列中后,将会等待一段时间才能获得调度。在设备空闲模式下,退避机制不会产生作用boolean onStartJob (JobParameters params)
JobService将会在这个回调方法获得可执行的任务,如果该任务不需要额外的执行,可以立即返回false。否则需要在单独的线程中执行(使用Handler),并且返回true,在任务执行完后调用jobFinished()方法进行通知boolean onStopJob (JobParameters params)
当你主动通知任务执行完毕(jobFinished)之前,系统可能会要求你停止任务,这时将会调用onStopJob方法
当该任务的需求不再满足时将发生这种状况,必须对此做出反应,否则应用可能会出现行为异常。一种立即引起的影响就是系统可能会将你的wakelock释放
返回true表示你希望对该任务重新进行调度,同样需要遵守退避策略;返回false表示你希望放弃该任务
关于JobScheduler API的学习大概就是这么多了,可以看到Google从Android L开始就很关注电池续航的问题,包括M的doze mode也是一样,估计N也会引入更好的省电策略。看到网上关于这块的中文资料都不是挺全面,于是就自己尝试对整个API进行学习,感觉还行吧,就酱。
另附:
官方Sample
JobScheduler官方文档
JobScheduler学习 附官方demo相关推荐
- 学习Tensorflow2官方Demo——Lenet,以及遇到的问题
目录 前言 1.官方Demo的项目目录 2.模型 3.训练 4.遇到的问题 前言 TensorFlow是一个面向所有开发人员的开源机器学习框架. 它用于实现机器学习和深度学习应用程序.为了开发和研 ...
- 学习Pytorch官方Demo——Lenet,以及遇到的问题
文章目录 1.官方Demo的项目目录 2.模型 3.训练 4.预测 5.遇到的问题 1.官方Demo的项目目录 2.模型 代码: import torch.nn as nn import torch. ...
- Android App支付系列(二):支付宝SDK接入详细指南(附官方支付demo)
前言 一家移动互联网公司,说到底,要盈利总是需要付费用户的,自己开发支付系统对于资源有限的公司来说显然不太明智,国内已经有多家成熟的移动支付提供商,阿里就是其中之一. 继< Android Ap ...
- CORE-ESP32C3|eink|日期格式化|IO11解锁|墨水屏操作库|SNTP自动同步|局部刷新|全局刷新|LuatOS-SOC接口|官方demo|学习(12):简单日期显示
目录 基础资料 探讨重点 参考博文: 实现功能 硬件准备 软件版本 日志及soc下载工具 软件使用 接线示意图 IO11解锁教程可参考: 功能1:基于墨水屏的日期显示: 初始化: 日期显示: 功能2: ...
- CORE-ESP32C3|eink|墨水屏日历|天气API|LuatOS公共接口|气象要素数据V1|collectgarbage|LuatOS-SOC接口|官方demo|学习(13):墨水屏动态日历
目录 参考博文 项目官方地址 显示效果: 硬件准备 软件版本 日志及soc下载工具 软件使用 接线示意图 硬件接线 一.Elink驱动管脚适配 二.天气信息获取 API使用方式: 接口格式(注意需不需 ...
- 合宙Air105|摄像头|capture|SPI|Serial 串口|TFTLCD|Micro SD卡|GC032A|USB转TTL|官方demo|学习(2-1):摄像头camera-capture
目录 基础资料 探讨重点 实现功能 硬件准备 软件版本 软件使用 接线示意图 功能1:捕捉图片并存入SPI接口外置SD卡 lcd初始化 摄像头初始化 指定capture按钮 SD卡初始化 图片存储 功 ...
- Android App支付:支付宝SDK接入详细指南(附官方支付demo)
Android App支付:支付宝SDK接入详细指南(附官方支付demo) 前言 一家移动互联网公司,说到底,要盈利总是需要付费用户的,自己开发支付系统对于资源有限的公司来说显然不太明智,国内已经有多 ...
- CORE-ESP32C3|eink|墨水屏日历+时间日期+温度显示|I2C软件模拟| LuatOS-SOC接口|官方demo|学习(14):墨水屏动态日历+oled日期显示+ AHT10测温模组
目录 参考博文 源于网友oled+eink+aht10项目 源代码修改及复现说明 主要修改 显示效果 编辑硬件准备 软件版本 日志及soc下载工具 软件使用 接线说明 天气显示屏 硬件接线 温度采集 ...
- gRPC学习记录(四)--官方Demo
了解proto3后,接下来看官方Demo作为训练,这里建议看一遍之后自己动手搭建出来,一方面巩固之前的知识,一方面是对整个流程更加熟悉. 官方Demo地址: https://github.com/gr ...
最新文章
- 16 条 yyds 的代码规范
- Python作为目前的大势,有哪些优势?
- 表单必填_forms. 表单(中)
- 实验吧--web--天下武功唯快不破
- docker 部署mysql服务之后,执行sql脚本
- 开发人员学Linux(2):VirtualBox中安装CentOS7系统设置
- 用了十年的昵称badboy_怎样用5秒钟看清一对夫妻的真实感情状况?
- MySQL并发复制系列二:多线程复制
- 超炫彩光效数码产品线条感海报PSD分层模板,炫亮抓你眼球
- java调整图片透明度
- OpenCL 学习step by step (5) 使用二维NDRange workgroup
- Server concepts 详解
- 开源的仿真软件HOPSAN
- echarts 生成 迁徙图_利用百度Echarts开发人口迁徙图(产品流向图)
- ios8正式版固件开放下载 有哪些亮点?
- 机器学习大作业---文献综述
- 使用Elasticsearch进行高效的中文搜索
- 不必急于吹响裁判哨:“安卓禁令”后华为手机的变数与新机
- mac 安装qemu的方法
- 如何登录数据库和运行
热门文章
- mysql导出为lua配置表文件_利用lua生成一个导出数据库的bat脚本文件
- 关于伺服驱动控制的课本_西门子伺服电机驱动系列汇总,说明书参数及使用方法。...
- UDP如何实现可靠传输
- ps查看oracle进程数,通过ps -ef | grep oracle查出的进程,怎样对应数据库中跑的进程...
- mysql mgr 5.6_mysql MGR高可用配置
- 2013秋浙大远程教育计算机应用基础-9计算机多媒体技术,2013秋浙大远程教育计算机应用基础-9...
- python爬取天天基金_用Python抓取天天基金网基金历史净值数据
- linux无法挂载移动硬盘6,FC6下挂载NTFS移动硬盘,无法读取
- 主成分分析 图像处理 matlab,matlab信号处理与主成分分析法,毕业设计求助
- 如何让弹窗不影响主界面_如何压缩视频大小不影响画质