android-job 调度任务

匿名 (未验证) 提交于 2019-12-03 00:41:02

Android-job

链接地址

JobManger

策略式调用不同策略实现调度任务,单例类,通常在app中进行初始化;
JobManager.create(this).addJobCreator(new XXXJobCreator());

初始化create JobManager时:
创建JobCreatorHolder, JobExecutor, JobStorage
也可开启重新调度的服务JobRescheduleService ;

创建完毕后通过sendAddJobCreatorIntent()方法:将JobCreator中的广播接受者的子类都通过addJobCreator(..)加入到
JobManager中管理;

JobApi

枚举类,所有异步调度的策略;

主要判断该策略是否支持环境,以及创建 JobProxy 的代理类;
JobProxy 为 每个JobApi的代理接口;提供 job的执行方式,一次性执行或周期性执行等,及Common常用方法;

JobProxy

JobManager schedule->两个booleanperiodic ,flexSupport 判断是Proxy调用不同的抽象方法 ->
planOneOff(request)/一次性的执行方法

planPeriodic(request)/重复性的执行方法

plantPeriodicFlexSupport(request) 重复性且灵活支持的执行方法;
由具体的实现去执行;
最后的实现都是通过Common的方法执行任务:

public Job.Result executeJobRequest(@NonNull JobRequest request, @Nullable Bundle transientExtras) {     //获取JobManager的JobExecutor 对象 ;     //将JobManager的JobCreatorHolder中的对象取出构建Job对象;     //使用执行者执行Job对象JobExecutor.execute(     context,request,job,transientExtras);获取Job.Result结果; }

JobCreatorHolder

包含一个List 容器 ,及操作容器,使用JobCreator快速建Job的方法;

JobExecutor

SpareArray mJobs;

LruCache \

JobApi中的策略 (implement JobProxy)

plantOneOff(JobRequest): 用来一次性调用方法; plantPeriodic(JobRequest): 用来周期性调用方法; plantPeriodicFlexSupport(JobRequest): 周期性且灵活支持各种版本的异步调度; cancel(int): 取消某一个Job的调度; isPlatformJobScheduled(JobRequest):
  • 使用WorkManager 调度任务(重要)

简介:
使用WorkManager实现;
具体的XXXWorker (PlatformWorker extends Worker) 实现具体的doWork操作:

最终是通过 JobProxy的Common类方法 executeJobRequest(JobRequest,Bundle)
->JobExecutor$JobCallable
->Job.runJob();
->abstract Result onRunJob(@NonNull Params params);

任务调度由WorkRequest的子类 PeriodicWorkRequest 重复工作的请求和OneTimeWorkRequest 非重复工作的请求 进行控制;

plantOneOff :

OneTimeWorkRequest.Builder(PlatformWorker.class)
设置JobRequest的参数,由WorkManger执行;

plantPeriodic:

plantPeriodicFlexSupport

PeriodicWorkRequest.Builder(PlatformWorker.class)
设置JobRequest的参数,由WorkManger执行;

WorkManager的简介和使用:

api:23+:  JobScheduler; api:14-22:  using Firebase JobDispatcher && Firebase dependency  ,使用Firebase JobDispatcher; 其他的使用自定义的AlarmManager + BroadcastReceiver 实现  所有的工作由相应的 `Worker` 去执行计算,执行在后台线程中;  WorkManger支持两种工作类型 即OneTimeWorkRequest 和PeriodicWorkRequest :  WorkManager workManager = WorkManager.getInstance(); workManager.enqueue(new OneTimeWorkRequest.Builder(FooWorker.class).build());}  *  WorkRequest 可使用id 用来观察和查找:  WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build(); workManager.enqueue(request); LiveData<WorkStatus> status = workManager.getStatusById(request.getId()); status.observe(...);}  也可使用id 去取消某一个Work:  WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build(); workManager.enqueue(request); workManager.cancelWorkById(request.getId());}</pre>   WorkRequest可以使用调用链:  WorkRequest request1 = new OneTimeWorkRequest.Builder(FooWorker.class).build(); WorkRequest request2 = new OneTimeWorkRequest.Builder(BarWorker.class).build(); WorkRequest request3 = new OneTimeWorkRequest.Builder(BazWorker.class).build(); workManager.beginWith(request1, request2).then(request3).enqueue();} 使用 beginWith(OneTimeWorkRequest...) or beginWith(List) 返回 WorkContinuation ;这允许创建复杂的构造者链; EG: A | +------+ |       | B       C | +------+ |       | D       E  WorkContinuation continuation=workManager.beginWith(A); continuation.then(B).then(D, E).enqueue(); continuation.then(C).enqueue();} A 是隐式的队列;  WorkRequest 能接受约束Constraints ,输入Data,返回 criteria; 工作链能给一个独一无二的标志名. 如:beginUniqueWork(String, ExistingworkPolicy , OneTimeWorkRequest ...)  默认情况下,WorkManager 运行在后台线程中,需要同步调用WorkManager时,使用synchronous();

  • 使用JobProxy21调度任务
  • 子类 JobProxy24JobProxy26 相同实现

简介:
使用 JobSchedulerJobService 实现;
构建JobInfo.Builder创建JobInfo ,通过设置JobRequest的参数达到将任务分离;
真正的执行逻辑运行于JobService中;

最终是通过 JobProxy的Common类方法 executeJobRequest(JobRequest,Bundle)
->JobExecutor$JobCallable
->Job.runJob();
->abstract Result onRunJob(@NonNull Params params);

plantOneOff

plantPeriodicFlexSupport

JobInfo设置JobInfo.Builder.setMinimumLatency(startMs).setOverrideDeadline(endMs)

plantPeriodic

JobInfo设置
JobInfo.Builder.setPeriodic(intervalMs);

设置不同参数,表示不同约束,使用JobScheduler调度;

JobScheduler的介绍和使用

JobScheduler  用于调度多种类型的job,构建了JobInfo对象后通过JobSceduler 调度JobInfo,符合规则条件时,会在JobService中执行job,初始化时通过getSystemService(Context.JOB_SCHEDULER_SERVICE); 具体的操作逻辑位于 JobService (PlatformJobService extends JobService extends Service 进程间的通信Binder实现)  ,JobConfig线程池中通过JobProxy.Common .getPendingRequest()方法获取JobRequest,标记为start状态后, 也是通过`Job.Result executeJobRequest(request,transientBundle)`方法执行任务 ->最终通过JobExecutor$JobCallable将执行结果回调给Job的子类;     JobInfo 的设置参数,构建一个基准的JobInfo,通过设置时间参数的不同达到不同的实现方式,即一次性实现和周期性实现; JobInfo 是一个封装 JobScheduler 需要参数 的数据容器;必须至少指定一个排序约束;[约束即设置周期或者设置开始时间结束时间等]  //创建一个通用的JobInfo,设置不同参数可控制约束; protected JobInfo.Builder createBaseBuilder(JobRequest request, boolean allowPersisting) {         JobInfo.Builder builder = new JobInfo.Builder(request.getJobId(), new ComponentName(mContext, PlatformJobService.class))                 .setRequiresCharging(request.requiresCharging())                 .setRequiresDeviceIdle(request.requiresDeviceIdle())                 .setRequiredNetworkType(convertNetworkType(request.requiredNetworkType()))                 .setPersisted(allowPersisting && !request.isTransient() && JobUtil.hasBootPermission(mContext));          return setTransientBundle(request, builder);     }

JobService

JobScheduler 的回调的入口点,这是一个处理异步预先调度请求的抽象基类; 重写onStartJob(JobParameters) 可实现job的逻辑; 这个service会在你的主线程使用Handler执行每个传入的job,意味着你必须把你的执行逻辑装到其他的线程/hander/AsyncTask 中;  优点:只需要重写onStartJob,即可使用线程池实现自己的逻辑;

  • 使用JobProxy14调度任务
  • 子类JobProxy19

简介:
使用 AlarmManagerBroadcastReceiverService(JobIntentService & 需设置唤醒锁Service)实现;

最终是通过 JobProxy的Common类方法 executeJobRequest(JobRequest,Bundle)
->JobExecutor$JobCallable
->Job.runJob();
->abstract Result onRunJob(@NonNull Params params);

获取BroadcastReceiver的Intent ,构造PendingIntent; Intent intent = PlatformAlarmReceiver.createIntent(mContext, jobId, exact, transientExtras); return PendingIntent.getBroadcast(mContext, jobId, intent, flags);  在api19中(AlarmManager 时间不精确): !request.isExact() 时重写 plantOneOffInexact 设置: alarmManager.setWindow(AlarmManager.RTC, startMs, lengthMs, pendingIntent); 以替换原先的alarmManager.set(AlarmManager.RTC, triggerAtMs, pendingIntent);

plantOneOff

精确时间时:

需要立即运行->开启服务PlatformAlarmService (extends SafeJobIntentService extends JobIntentService extends Service)->执行 Common.executeJobRequest(request,transientExtras)方法…

不需立即运行->设置alarmManager的参数,PendingIntent执行PlatformAlarmReceiver 的onReceive(..)

->不是精确时间->
开启服务PlatformAlarmService(extends SafeJobIntentService extends JobIntentService extends Service) ->onHandleWork(Intent)运行runJob()静态方法->
Common.executeJobRequest(request,transientExtras)方法…

>

->是精确时间->开启服务PlatformAlarmServiceExact(extends Service) ->
因为广播接受者中开启服务 ,需要设置唤醒锁(PowerManager)
->onStartCommand JobConfig线程池执行 Common.executeJobRequest(request,transientExtras)方法…
->释放唤醒锁;

plantPeriodicFlexSupport

设置AlarmManager 的属性 alarmManager.set(AlarmManager.RTC, triggerAtMs, pendingIntent);,PendingIntent执行PlatformAlarmReceiver 的onReceive(..)-> 跟plantOneOff一致;

plantPeriodic

设置AlarmManager 的属性Repeating(),PendingIntent执行PlatformAlarmReceiver 的onReceive(..)->跟plantOneOff一致;

PendingIntent

延迟Intent,描述一个Intent和执行跳转目标action; 创建by getActivity getActivities ,getBroadcast,getService;  其返回的对象 能够被传递到其他应用里,可以执行你指定延迟加载的action ; 构建PengingIntent ,必须提供一个显示的component name的Intent,PendingIntent 本身是一个简单的引用记号(token), 被用于检索原始数据的系统所维持;意味着 ,即使它本身的应用进程被杀死,pendingIntent 也会被其他已经联系的进程保持可用状态; 注意 一个常见的错误是建造了多个PendingIntent对象, 使用只是他们的extra不一样的Intent构建,这样得到相同的PendingIntent对象; 

AlarmManager

mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 该类允许你调度你的应用在某一时刻运行;当alarm 定时已到,被系统广播注册的Intent,如果还没有运行的目标应用会自动开始运行;当设备是处于睡眠状态时(也可以在定时到了选择性的唤醒设备)注册alarms时可保留的,但是设备关机或重启时会被清除; alarm 的receiver 方法执行的情况下,alarm manager会一直持有Cpu的唤醒锁;这可以保证手机不会睡眠直到你结束了广播接受者的处理;一旦onReceiver 返回了 ,alarm manager 释放唤醒锁;意味着手机在一些情况下 当你的onReceive()完成后会很快的进入睡眠状态;  如果此时你的alarm receiver 调用 Context.startService(). 很可能在你请求服务启动之前,手机将会睡眠; 因此,你的广播接受者和服务需要实现一个单独的唤醒锁策略保证手机能持续运行知道服务成为可获得的; 从api19开始,  alarm 传递是不精确的,OS 偏移alarms 时间为了最小化唤醒和电池的使用.new的api 支持需要严格保证传递的应用,setWindow(int ,long ,long PendingIntent) and  setExact(int ,long,long ,PendingIntent); 

JobIntentService

对在一个job/service的队列中且正在进行的work提供帮助的类 ;api>Version_codes_o work 将作为一个job通过JobScheduler传递;其他将使用startService(); 使用enqueueWork(Context,CLass,int,Intent) 去将一个new work 加入队列,被你的service分发且处理,在onHandlerWork(Intent)中执行; 使用这个类时,不需要使用WakeFulBroadcastReceiver (带唤醒锁). 当运行在version_code_o时,JobScheduler 将关注唤醒锁(从你的work在队列中时持有唤醒锁直到job 传递已被传递且正在运行).其他版本中,这里唤醒锁的处理模拟了直接调用PowerManager的处理;意味着应用必须要求 permission.WAKE_LOCK权限; 运行在version_codes_o 上及以后,作为Job或pre-0 不同的几点:  当做 pre-0 service 运行:  enqueueing work 的动作将立即开启服务,无视设备睡眠后其他条件下;  正常的服务执行语义也适用:service能够无限期的运行,尽管它运行的时间越长越可能被彻底的杀死进程,并且在低内存压力下即使最近开启了service也应该希望进程被杀死;  当做 job 运行:  它隶属于标准的JobScheduler 策略 .作为一个当setOverrideDeadline(long)为0 的情况下的job,当设备睡眠状态(dozing) 时可以不会运行; 可能会延时很久; 典型的执行时间限制(如:JobService)适用:当job被stopped(清除,但没有杀死进程) 并且重新调度稍后会继续执行的情况下,job一般情况下在低内存压力不会被杀死,因为并发的job数量基于设备的内存状态被调整了;  最大的优点是不需要设置唤醒锁,使用onHandlerWork方便;
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!