美文网首页
JobScheduler相关

JobScheduler相关

作者: wind_sky | 来源:发表于2019-07-31 19:35 被阅读0次

    一. 介绍

    JobScheduler 是API 21(Android 5.0)新加入的,在7.0时提供了当ContentProvider发生变化时触发job的支持。JobScheduler的主要功能是将我们需要定时或者特定条件的事件交给系统,当系统满足条件(至于如何设置这些条件,将在JobInfo 、JobInfo.Builder和JobInfo.TriggerContentUri篇中进行介绍)的时候,就会回调我们的组件,运行我们的代码,并且在执行的过程中会回调我们的方法。JobScheduler会将满足条件的job打包执行,这样可以使设备有机会保持更长时间的休眠状态,从而节约了电量。

    在Android 8.0 中,由于后台执行限制,应用无法使用清单注册隐式广播,一些基于隐式广播的功能可能受到影响,这时我们可以使用JobScheduler进行相关替代。

    二. 使用

    1. 创建JobService

    JobService是调度程序的回调入口,我们要执行的任务就在这里实现,需要继承JobService,并重写相关方法,例如

    public class TestJobService extends JobService{
    
        private Handler mHandler = new MyHandler(this);
    
        @Override
        public boolean onStartJob(JobParameters jobParameters) {
            Message message = Message.obtain();
            message.obj = jobParameters;
            mHandler.sendMessage(message);
    
            return true;
        }
    
        @Override
        public boolean onStopJob(JobParameters jobParameters) {
            mHandler.removeCallbacksAndMessages(null);
            return false;
        }
    
        static class MyHandler extends Handler {
    
            private WeakReference<TestJobService> reference;
    
            MyHandler(TestJobService service) {
                reference = new WeakReference<>(service);
            }
    
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
    
                TestJobService service = reference.get();
                if (service != null) {
                    Toast.makeText(service, "hhhhhhhhhhhh", Toast.LENGTH_SHORT).show();
                    JobParameters parameters = (JobParameters) msg.obj;
                    service.jobFinished(parameters, true);
    
                    Intent intent = new Intent(service, JobServiceActivity.class);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    service.startActivity(intent);
                }
            }
        }
    }
    

    当我们开始任务时,onstartjob(jobparameters params) 是必须使用的方法,因为它是系统用来触发已经安排的工作的。该方法返回一个布尔值。如果返回值是false,该系统假定任何任务运行不需要很长时间并且到方法返回时已经完成。如果返回值是true,那么系统假设任务是需要一些时间并且负担落到开发者的身上,当给定的任务完成时通过调用jobFinished(JobParameters params, boolean needsRescheduled)告知系统。

    当收到取消请求时,onStopJob(JobParameters params) 是系统用来取消挂起的任务的。重要的是要注意到,如果onStartJob(JobParameters params)返回 false,当取消请求被接收时,该系统假定没有目前运行的工作。换句话说,它根本就不调用onStopJob(JobParameters params)。

    有一点要注意的是,工作服务在应用程序的主线程上运行。所以,如果要在Service中执行耗时任务,需要创建一个工作线程。

    当任务完成时,需要调用jobFinished(JobParameters params, boolean needsRescheduled)让系统知道已经完成了那项任务,它可以开始排队接下来的操作。如果不这样做,这个工作将只运行一次,我们的应用程序将不被允许执行额外的工作。

    在onStartJob(JobParameters params)方法中,jobFinished(JobParameters params, boolean needsRescheduled) 的两个参数值是JobParameters传递到JobService类,一个布尔值让系统知道是否需要根据工作的最初要求重新编排工作。这个布尔值对于理解是非常有用的,因为它帮助我们了解如何处理因其他问题(如一个失败的网络电话)而导致任务无法完成的情况。

    注意:因为JobService是Service的子类,所以需要在manifest文件中注册,同时需要声明权限

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

    2. 创建JobScheduler

    JobScheduler对象不能直接new,而是有特别创建方式,在Activity中使用如下代码

    JobScheduler jobScheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
    

    调度一个任务将被执行时,通过下面代码

    jobScheduler.schedule(jobInfo);
    

    JobInfo类通过Builder模式封装了工作要执行的相关条件,用如下方法创建

    JobInfo jobInfo = new JobInfo.Builder(233, new ComponentName(getPackageName(), TestJobService.class.getName()))
            .setPeriodic(2000)
            .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
            .build();
    

    JobInfo提供的诸多条件,将在JobInfo 、JobInfo.Builder和JobInfo.TriggerContentUri篇中介绍。

    在执行schedule方法时,如果发现id相同的job,原job将被取代,如果这个job正在执行将会被停止。schedule操作返回一个整数。如果schedule 失败,它将返回一个为零或更少的值,对应于一个错误代码。否则,它将返回在JobInfo.Builder中定义的作业标识符。如果应用程序需要停止特定或所有工作,可以通过对JobScheduler 对象调用cancel(int jobId)或cancelAll()实现。

    在JobScheduler的API中,除了schedule方法,还有enqueue方法

    jobScheduler.enqueue (jobInfo, workItem);
    

    enqueue方法和schedule方法类似,但是允许我们为已经存在或者新的Job入队一个work,如果拥有相同id的job已经被调度,那么将会被新的JobInfo取代,但是已经入队的work会被保留,并在下次运行的时候被分发,如果有相同id的job已经在运行,那么work将会被入队其中。入队的work将在稍后被JobParameters.dequeueWork取回,要明确地知道怎样处理work,因为它会影响之前处理job生命周期的方法。

    建议向同一个job进行enqueue,可以使系统更优化的调度work,因为如果JobInfo改变,系统需要改变相关关联,导致运行中断等。

    在enqueue工作时,JobInfo尽量避免执行 setExtras(PersistableBundle) 或者 setTransientExtras(Bundle),因为这样会让系统与已经存在的JobInfo比较extra,可能导致错误产生。并且不要调用setClipData(ClipData, int) 方法,因为系统会认为这是一个新的JobInfo,即使内容相同。

    相关文章

      网友评论

          本文标题:JobScheduler相关

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