WorkManager之SystemJobScheduler、SystemAlarmScheduler、GreedyScheduler使用场景分析(未完)

 

1、先来说说SystemJobScheduler

api>=23使用,持有JobScheduler(5.0引入),由系统底层支持的调度服务,单个进程分配10个调度任务。

如下Configuration.java类计算最大可调度次数,api=23最大可调度25个,api>23可调度50个,所以一般来说足够了。所以api>=23大多数情况应该就是使用SystemJobScheduler。

    // 如下代码计算最大的可调度个数
    // int MAX_SCHEDULER_LIMIT = 50;
    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    @IntRange(from = Configuration.MIN_SCHEDULER_LIMIT, to = Scheduler.MAX_SCHEDULER_LIMIT)
    public int getMaxSchedulerLimit() {
        // We double schedule jobs in SDK 23. So use half the number of max slots specified.
        if (Build.VERSION.SDK_INT == 23) {
            return mMaxSchedulerLimit / 2;
        } else {
            return mMaxSchedulerLimit;
        }
    }

 见SystemJobScheduler指定hasLimitedShedulingSlots=true。

    //见SystemJobScheduler实现的Scheduler的如下接口
    @Override
    public boolean hasLimitedSchedulingSlots() {
        return true;
    }

 下面是Schedulers.java中schedule()方法的部分代码,看出控制了在限度范围内的workSpec才会被 hasLimitedShcedulingSlots=true的调度器调度。

public static void schedule(
            @NonNull Configuration configuration,
            @NonNull WorkDatabase workDatabase,
            List<Scheduler> schedulers) {
        //此处省略部分无关代码
        // Enqueued workSpecs when scheduling limits are applicable.
            eligibleWorkSpecsForLimitedSlots =        workSpecDao.getEligibleWorkForScheduling(
                    configuration.getMaxSchedulerLimit());
        
        // 此处省略部分无关代码

        if (eligibleWorkSpecsForLimitedSlots != null
                && eligibleWorkSpecsForLimitedSlots.size() > 0) {

            WorkSpec[] eligibleWorkSpecsArray =
                    new WorkSpec[eligibleWorkSpecsForLimitedSlots.size()];
            eligibleWorkSpecsArray =
                    eligibleWorkSpecsForLimitedSlots.toArray(eligibleWorkSpecsArray);

            // Delegate to the underlying schedulers.
            for (Scheduler scheduler : schedulers) {
                if (scheduler.hasLimitedSchedulingSlots()) {
                    scheduler.schedule(eligibleWorkSpecsArray);
                }
            }
        }

如果满足条件的Worker超过计算的调度槽数,就会交给hasLimitedShcedulingSlots=false的调度器,实际上就是GreedyScheduler见如下代码块

if (allEligibleWorkSpecs != null && allEligibleWorkSpecs.size() > 0) {
            WorkSpec[] enqueuedWorkSpecsArray = new WorkSpec[allEligibleWorkSpecs.size()];
            enqueuedWorkSpecsArray = allEligibleWorkSpecs.toArray(enqueuedWorkSpecsArray);
            // Delegate to the underlying schedulers.
            for (Scheduler scheduler : schedulers) {
                if (!scheduler.hasLimitedSchedulingSlots()) {
                    scheduler.schedule(enqueuedWorkSpecsArray);
                }
            }
        }

 下面是最终调度代码,使用持有的JobScheduler实例

    /**
     * Schedules one job with JobScheduler.
     *
     * @param workSpec The {@link WorkSpec} to schedule with JobScheduler.
     */
    @VisibleForTesting
    public void scheduleInternal(WorkSpec workSpec, int jobId) {
        JobInfo jobInfo = mSystemJobInfoConverter.convert(workSpec, jobId);
        Logger.get().debug(
                TAG,
                String.format("Scheduling work ID %s Job ID %s", workSpec.id, jobId));
        try {
            int result = mJobScheduler.schedule(jobInfo);

接下来JobScheduler在引爆之后会交给SystemJobService的startJob()方法如下代码

    @Override
    public boolean onStartJob(@NonNull JobParameters params) {
        // 省略一大段代码
        // For more information look at b/123211993
        mWorkManagerImpl.startWork(workSpecId, runtimeExtras);
        return true;
    }

2、再来说说SystemAlarmScheduler:

api<23使用,和SystemJobScheduler一样都是系统级的调度服务,也是单进程限制个数的调度任务,顾名思义就是使用AlarmService进行定时调度。跟SystemJobSchedule是相互替代作用,作用也一致。调度器引爆后会交给SystemAlarmService

3、最后说说GreedyScheduler:

当调度的workSpec超出系统提供的两类Scheduler的槽数限制时,就会使用GreedyScheduler来调度,当然也是有大小限制的见如下代码

    /**
     * The maximum number of {@link WorkSpec}s that are considered for execution by the greedy
     * scheduler.
     */
    int MAX_GREEDY_SCHEDULER_LIMIT = 200;

下面是schedule()方法中的关键行,延迟调度和立即执行。延迟调度最终使用的就是Handler

mHandler.postDelayed(runnable, delayInMillis);
@Override
public void schedule(@NonNull WorkSpec... workSpecs) {

//此处省略部分代码
if (now < nextRunTime) {
    // Future work
    if (mDelayedWorkTracker != null) {
        mDelayedWorkTracker.schedule(workSpec);
    }
}

// 此处省略部分代码
mWorkManagerImpl.startWork(workSpec.id);

}

 立即执行部分,使用的是WorkManagerImpl初始化时创建的线程池来执行runnable

public void startWork(
            @NonNull String workSpecId,
            @Nullable WorkerParameters.RuntimeExtras runtimeExtras) {
        mWorkTaskExecutor
                .executeOnBackgroundThread(
                        new StartWorkRunnable(this, workSpecId, runtimeExtras));
    }

综上是目前看到的部分,还有一些还没看完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值