- 一、JobScheduler 提交任务 schedule 方法源码分析
- 二、schedule(JobInfo job, int uId) 方法
- 三、scheduleAsPackage 方法
- 四、startTrackingJob 方法
- 五、JobSchedulerService 源码注释
上一篇博客 【Android 电量优化】电量优化 ( JobScheduler | JobService | AsyncTask ) 中使用了 JobScheduler 进行电量优化 , 将消耗电量的操作 , 都在设定的条件下集中执行 , 达到减少唤醒硬件的频率 , 省电的目的 ; 本篇博客中从源码角度分析上述操作的底层原理 ;
推荐代码查看网站 :
-
https://www.androidos.net.cn/sourcecode ( 推荐 )
-
http://androidxref.com/
JobScheduler 的功能依赖 JobSchedulerService 系统服务完成 ;
使用 JobScheduler 对象提交任务的方法 schedule(jobInfo) , 最终跨进程调用的 JobSchedulerService 中的 int schedule(JobInfo job, int uId) 方法 ;
二、schedule(JobInfo job, int uId) 方法JobSchedulerService 中的 int schedule(JobInfo job, int uId) 方法解析 :
JobScheduler 的提交任务方法 schedule , 最终调用到 int schedule(JobInfo job, int uId) 方法 , 该调用是跨进程调用的 ;
int schedule(JobInfo job, int uId) 方法 是客户端的 JobScheduler 调用 schedule 方法执行后的入口函数 , 提供一个 JobInfo job 任务 ; 如果任务已经被安排 , 那么取消该任务 , 并使用新传入的该 JobInfo job 参数代替原来的任务 ;
三、scheduleAsPackage 方法在 int schedule(JobInfo job, int uId) 方法中 , 实际调用了 int scheduleAsPackage(JobInfo job, int uId, String packageName, int userId, String tag) 方法 ,
参数说明 :
- job 任务信息
- uId 任务 id
- packageName 包名
- userId 用户 id ;
在上述 scheduleAsPackage 方法中 , 进行了一系列的状态判定 , 如包名不能为空 , 当前任务数量没有超过最大值 MAX_JOBS_PER_APP , 如果上述判定通过 , 就调用 void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) 方法 , 该方法用于追踪任务状态 ;
四、startTrackingJob 方法当我们有一个任务状态对象 , 我们需要插入到 JobStore 时 , 回调 void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) 方法 , 确保所有相关的控制器知道该状态 ;
以下控制器需要知道任务状态 :
- ConnectivityController
- TimeController
- IdleController
- BatteryController
- AppIdleController
- ContentObserverController
- DeviceIdleJobsController
这些控制器都封装在 List mControllers 成员变量中 , 该集合是 JobSchedulerService 的成员变量 ;
上述控制器在 public JobSchedulerService(Context context) 构造函数中初始化并放入 mControllers 集合中 ;
五、JobSchedulerService 源码注释public class JobSchedulerService extends com.android.server.SystemService
implements StateChangedListener, JobCompletedListener {
/** 任务的主要集合. */
final JobStore mJobs;
/** 控制器集合 , 提醒该 Service 服务区更新任务. */
List mControllers;
/**
* 初始化系统服务
*
* 子类必须定义一个单参数的构造函数 , 接收 Context context 参数 , 并且传递给父类
*
*
* @param context 系统服务上下文对象
*/
public JobSchedulerService(Context context) {
super(context);
mHandler = new JobHandler(context.getMainLooper());
mConstants = new Constants(mHandler);
mJobSchedulerStub = new JobSchedulerStub();
mJobs = JobStore.initAndGet(this);
// 创建控制器集合
// 后续会遍历该集合 , 遍历出的元素会调用 maybeStartTrackingJobLocked 方法
mControllers = new ArrayList();
// 网络控制器
mControllers.add(ConnectivityController.get(this));
mControllers.add(TimeController.get(this));
mControllers.add(IdleController.get(this));
// 电量控制器
mControllers.add(BatteryController.get(this));
mControllers.add(AppIdleController.get(this));
mControllers.add(ContentObserverController.get(this));
mControllers.add(DeviceIdleJobsController.get(this));
}
// JobScheduler 的提交任务方法 schedule , 最终调用到该方法
// 跨进程方式调用
// 这是客户端的 JobScheduler 调用 schedule 方法执行后的入口函数 , 提供一个 JobInfo job 任务 ;
// 如果任务已经被安排 , 那么取消该任务 , 并使用新传入的该 JobInfo job 参数代替原来的任务 ;
public int schedule(JobInfo job, int uId) {
return scheduleAsPackage(job, uId, null, -1, null);
}
// 实际调用的方法 , 传入 JobInfo job 任务信息 , uId 任务 id , packageName 包名 , userId 用户 id ,
public int scheduleAsPackage(JobInfo job, int uId, String packageName, int userId,
String tag) {
// 创建任务状态
JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);
// ... 省略
JobStatus toCancel;
synchronized (mLock) {
// 判定状态是否合法 , 包名不能为空 , 当前任务数量没有超过最大值 MAX_JOBS_PER_APP
if (ENFORCE_MAX_JOBS && packageName == null) {
if (mJobs.countJobsForUid(uId) > MAX_JOBS_PER_APP) {
Slog.w(TAG, "Too many jobs for uid " + uId);
// 如果多于最大任务数 , 就要抛出异常
throw new IllegalStateException("Apps may not schedule more than "
+ MAX_JOBS_PER_APP + " distinct jobs");
}
}
toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
if (toCancel != null) {
cancelJobImpl(toCancel, jobStatus);
}
// 如果上述判定通过 , 就调用该方法 , 该方法用于追踪任务状态
startTrackingJob(jobStatus, toCancel);
}
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
return JobScheduler.RESULT_SUCCESS;
}
/**
* 当我们有一个任务状态对象 , 我们需要插入到 JobStore 时 , 回调该方法 ,
* 确保所有相关的控制器知道它 ;
*/
private void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) {
synchronized (mLock) {
// 将本次调度的任务加入到 JobStore mJobs 集合中
final boolean update = mJobs.add(jobStatus);
if (mReadyToRock) {
// 遍历控制器集合 List mControllers
for (int i = 0; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?