美文网首页
JobScheduler详解

JobScheduler详解

作者: NoBugException | 来源:发表于2022-01-02 12:40 被阅读0次

JobScheduler 是将任务(Job)放到后台,当预制的条件被满足时,这些Job会在后台被执行。
通常情况下,我们会把一些不是特别紧急的任务放到更加合适的时机来批量处理,这样做不仅可以避免频繁的唤醒硬件模块,还避免了在不合适的时候执行一些耗电任务。

一、JobScheduler如何使用?

[第一步] 创建JobService类

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class MyJobService extends JobService {

    private Handler mHandler = new Handler(Looper.getMainLooper()){

        @Override
        public void handleMessage(@NonNull Message msg) {
            if (msg.obj instanceof JobParameters) {
                JobParameters params = (JobParameters) msg.obj;
                jobFinished(params, false);
            }
        }
    };

    @Override
    public boolean onStartJob(final JobParameters params) {
        Message message = mHandler.obtainMessage();
        message.obj = params;
        mHandler.sendMessage(message);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return true;
    }

}

JobService 本质上是Service,所以,需要在注册表中注册

    <service android:name=".MyJobService"
        android:permission="android.permission.BIND_JOB_SERVICE" />

注意,必须要添加android.permission.BIND_JOB_SERVICE权限,否则会报错。

[第二步] 创建JobInfo,通过builder设定Job的执行选项

        JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        JobInfo.Builder builder = new JobInfo.Builder(1, new ComponentName(this, MyJobService.class));
        builder.setMinimumLatency(2000); // 最短延迟时间
        builder.setOverrideDeadline(10000); // 最长延迟时间

JobInfo.Builder的第一个参数是jobId,由开发者指定。
setMinimumLatencysetOverrideDeadline 是预设的条件,setMinimumLatency是最短延迟时间,setOverrideDeadline是最长延迟时间。

[第三步] 获取JobScheduler服务执行任务

        jobScheduler.schedule(builder.build());
二、Job的执行条件有哪些?

JobScheduler 是将任务(Job)放到后台,当预制的条件被满足时,这些Job会在后台被执行。
这些预制条件是由JobInfo指定的,那么有哪些预制条件呢?

builder.setMinimumLatency(2000);
可以设置最短延迟时间,即工作的最早执行时间是2秒。

-----------------------------

builder.setOverrideDeadline(10000);
可以设置最长延迟时间,即工作的最迟执行时间是10秒。

-----------------------------

builder.setBackoffCriteria(TimeUnit.SECONDS.toMillis(10), JobInfo.BACKOFF_POLICY_LINEAR);
触发重试,Job的执行总是会执行 onStartJob 方法,一旦触发重试,那么会重新执行 onStartJob 方法。
第一个参数是initialBackoffMillis,意思是:作业失败时最初等待的毫秒时间间隔。
第二个参数是backoffPolicy,意思是重试策略(重试方案),它定义了两种重试方案:
    JobInfo.BACKOFF_POLICY_LINEAR:线性重试方案
    公式为:retry_time(current_time, num_failures) = current_time + initial_backoff_millis * num_failures, num_failures >= 1
    JobInfo.BACKOFF_POLICY_EXPONENTIAL:指数重试方案
    公式为:retry_time(current_time, num_failures) = current_time + initial_backoff_millis * 2 ^ (num_failures - 1), num_failures >= 1

-----------------------------

Uri uri = Uri.parse("content://com.test.aaa/ccc");
ClipData clipData = ClipData.newUri(getContentResolver(), "URI", uri); // 将URI数据放到ClipData中
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    builder.setClipData(clipData, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
setClipData的主要目的是将剪切板数据授予URI权限。
setClipData的第二个参数为权限,这个权限只对URI数据有效(ClipData可以存储`字符串`、`Intent`、`URI`)。
第二个参数可以指定的权限有:FLAG_GRANT_READ_URI_PERMISSION、FLAG_GRANT_WRITE_URI_PERMISSION、FLAG_GRANT_PERSISTABLE_URI_PERMISSION、FLAG_GRANT_PREFIX_URI_PERMISSION
FLAG_GRANT_READ_URI_PERMISSION:URI读权限
FLAG_GRANT_WRITE_URI_PERMISSION:URI写权限
FLAG_GRANT_PERSISTABLE_URI_PERMISSION:URI权限授予可以坚持在设备重新启动直到明确撤销,用revokeuripermission
FLAG_GRANT_PREFIX_URI_PERMISSION:URI权限授予适用于任何前缀匹配不同于原始的授予的URI

-----------------------------

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    builder.setEstimatedNetworkBytes(1000, 1000);
}
设置此作业将执行的网络流量的估计大小,单位为字节。
请注意,当设备的网络连接较差时,系统可能会选择使用较大的网络使用量估计来延迟作业,以节省电池和可能的网络成本。

-----------------------------

if (Build.VERSION.SDK_INT >= 31) {
    builder.setExpedited(true);
}
setExpedited是Android 12(API 31)新增接口,如果设置为true,说明Job比较重要,需要加速执行。

-----------------------------

PersistableBundle extras = new PersistableBundle();
extras.putString("name", "value");
builder.setExtras(extras);
设置持久化数据,可以通过 `builder.build().getExtras()` 获取。

-----------------------------

builder.setPeriodic(1000);
设置周期时间,可以任意设置周期的时间,当前设置的是1000毫秒,每1秒执行一次Job。
`setPeriodic` 与 `setMinimumLatency` 、 `setOverrideDeadline` 冲突,不能同时存在。
在Android 7.0(API 24)开始,新增接口如下:
    public Builder setPeriodic(long intervalMillis, long flexMillis)
intervalMillis是周期时间,flexMillis为弹性时间,并且将intervalMillis的最小时间设定为15分钟,将flexMillis的最小时间设定为5分钟。
Android 7.0(API 24)开始,如果您设置的周期时间小于15分钟,就默认设置为15分钟;如果您设置的弹性时间小于5分钟,就默认为5分钟。

-----------------------------

builder.setPersisted(true);
设置是否跨设备重新启动来持久化此作业。
如果为true,表示作业将被写入到磁盘,并在启动时加载。

-----------------------------

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    builder.setPrefetch(true);
}
Android 9.0(API 28)新增接口。
将此值设置为true表示此Job旨在预取内容,以改善该设备的特定用户的体验。
例如,获取当前用户感兴趣的头条。

-----------------------------

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    builder.setRequiredNetwork(NetworkRequest networkRequest);
}
设置一个网络请求对象,Android 9.0(API 28)新增接口。

-----------------------------

builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE);
设置网络类型,可以设置的网络类型有
NETWORK_TYPE_NONE:无网络或者有网络的时候执行Job
NETWORK_TYPE_ANY:执行Job需要网络连接(无网络不执行)
NETWORK_TYPE_UNMETERED:执行Job需要未设置按流量计费的网络连接(按流量计费的网络:连接到此网络时,
    某些应用可能具有不同的功能以减少数据使用,可以设置流量上限,以帮助控制在此网络上的数据使用量)
NETWORK_TYPE_NOT_ROAMING:执行Job需要未漫游的网络连接
NETWORK_TYPE_CELLULAR:执行Job需要蜂窝网络连接(蜂窝网络又称移动网络)

-----------------------------

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    builder.setRequiresBatteryNotLow(true);
}
指定要运行此作业,设备的电池电量不能很低。
默认为false。如果为true,该作业只会在电池电量不低时运行,这通常是用户得到电池电量不足警告的点。

-----------------------------

builder.setRequiresCharging(true);
如果为true,执行此作业,设备必须是充电状态(或是连接到永久电源的非电池供电设备,如安卓电视设备)。
默认为false。

-----------------------------

builder.setRequiresDeviceIdle(true);
设置为true时,如果设备处于活动使用状态,此作业不会运行,当设备处于空闲状态时,会执行此作业。
默认状态是false,也就是说,即使有人在与设备交互,作业也可以运行。

-----------------------------

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    builder.setRequiresStorageNotLow(true);
}
指定要运行此作业,设备的可用存储空间不能很低。
默认为false。
如果为true,则该作业将只在设备不处于低存储状态时运行,这通常是向用户提供低存储警告的点。

-----------------------------

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    Bundle bundle = new Bundle();
    bundle.putString("key", "value");
    builder.setTransientExtras(bundle);
}
设置临时数据(非持久化数据)

-----------------------------

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    builder.addTriggerContentUri(uri);
}
监听uri对应的数据发生改变,就会触发任务的执行。

-----------------------------

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    builder.setTriggerContentMaxDelay(long duration);
}
设置Content发生变化一直到任务被执行中间的最大延迟时间

-----------------------------

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    builder.setTriggerContentUpdateDelay(long duration);
}
设置Content发生变化一直到任务被执行中间的延迟。如果在这个延迟时间内content发生了改变,延迟时间会重写计算。
三、Job的执行和结束

Job被执行时,JobServiceonStartJob就会被执行,onStartJob中执行任务,这个任务可能是耗时的,可以将耗时任务放在另一个线程执行。

onStartJob是有返回值的。
如果为false,那么说明Job执行完毕。
如果为true,说明Job还没有执行完成,此时的任务是放在另一个线程执行的耗时任务,当这个耗时任务执行完成时,应该主动jobFinished方法,告诉系统该Job已经执行完成。

当执行 jobScheduler.cancel 或者 jobScheduler.cancelAll 时,并且该Job还没有执行完,那么 onStopJob 方法被执行。
onStopJob 的返回值如果为false时,表示不需要重试,为true时,表示需要重试。

[本章完...]

相关文章

  • JobScheduler详解

    JobScheduler 是将任务(Job)放到后台,当预制的条件被满足时,这些Job会在后台被执行。通常情况下,...

  • JobScheduler

    JobScheduler JobScheduler是Android L(API21)新增的特性,用于定义满足某些条...

  • 从JobScheduler到WorkManager

    JobScheduler介绍 JobScheduler是一个任务调度的类。它与AlarmManager不同的是这个...

  • SparkStreaming源码之JobScheduler

    SparkStreaming源码之JobScheduler篇 首先看下JobScheduler这个类是在什么时候被...

  • Android省电的秘密之JobScheduler

    JobScheduler是Android L版本新引入的API,JobScheduler,顾名思义,是用来调度工作...

  • JobScheduler

    什么是jobScheduler jobscheduler是 android 在5.0上针对降低功耗而提出的一种策略...

  • JobScheduler

    概述 JobScheduler是安卓5.0版本推出的API,允许开发者在符合某些条件时创建执行在后台的任务。在An...

  • JobScheduler

    JobScheduler简介 JobScheduler在api 21被引入,作为一个系统服务,它可以用于统一的调度...

  • jobscheduler精华

    参考源码: JobInfo 以及 JobScheduler

  • JobScheduler的使用和原理

    1、JobScheduler的使用 1.1 简介 JobScheduler主要用于在未来某个时间下满足一定条件时触...

网友评论

      本文标题:JobScheduler详解

      本文链接:https://www.haomeiwen.com/subject/hiqfqrtx.html