【Xamarin.Android】在Android Oreo 8.0中用作业替换服务

2650阅读 0评论2017-12-04 renxiao2003
分类:Android平台

在Android 8.0之前,即使应用程序在后台,Android应用程序也会启动几乎无限期运行的服务。 这项服务对于应用程序来说非常方便,开发人员也很容易实现,但是也会对用户的设备体验造成灾难性的影响。
作为一个例子,想象一下当一个设备插入充电时,许多应用程序想要执行工作的场景。 发生这种情况时,Android将调度android.intent.action.ACTION_POWER_CONNECTED意图。 所有已注册的应用程序都将启动,要求RAM,CPU时间和带宽。 发生这种情况时,这些同时发生的请求可能会超出设备上的可用空间,导致速度变慢。 在这一点上,用户都知道,他们插入设备,并开始表现出迟钝,反应迟钝的行为,并可能认为他们的手机有问题,或者他们需要购买更多的内存。

Android 8.0引入了新的后台执行限制,极大地改变了服务的工作方式。 当应用程序进入后台时,他们启动的任何服务将被授予几分钟时间,以在操作系统终止它们之前完成其工作。 Android Framework JobScheduler是解决Xamarin.Android应用程序针对Android 5.0(API级别21)或更高版本的更改的一种可能方式。
Android框架JobScheduler是一个API,用于在各种应用程序的后台运行不同的工作单元。 JobScheduler根据应用程序可以设置的条件安排哪些作业在适当的时间运行。 回到我们原来收取设备的例子,JobScheduler可能会安排这些工作,以便他们一个接一个地运行,而不是同时运行。

计划和排队作业的能力使JobScheduler完美适用于传统上由长时间运行的服务处理的任务,例如:

JobScheduler API中有三个重要的类:

JobService子类必须重写两个方法:

为了安排工作,应用程序需要使用JobInfo.JobBuilder来创建一个JobInfo对象。 JobInfo.JobBuilder有一个流畅的接口,用于收集元数据,例如要实例化的JobService的类型以及在作业运行之前应该满足的任何条件。 这段代码展示了如何创建一个JobInfo类来运行FibonacciJob(从上面的例子),但只有当设备连接到“未计量”(免费)的网络。 工作不应该比预定的时间快一秒钟,但应该在五秒内运行:

点击(此处)折叠或打开

  1. Java.Lang.Class javaClass = Java.Lang.Class.FromType(typeof(FibonacciJob);
  2. ComponentName component = new ComponentName(context, javaClass);
  3.  
  4. JobInfo.Builder builder = new JobInfo.Builder(context, component)
  5.                                      .SetMinimumLatency(1000) // Wait at least 1 second
  6.                                      .SetOverrideDeadline(5000) // But no longer than 5 seconds
  7.                                      .SetRequiredNetworkType(NetworkType.Unmetered);
  8. JobInfo jobInfo = builder.Build();

在前面的例子中,上下文是任何Android上下文,比如一个Activity。 该参数是一个唯一的整数,用于标识JobScheduler的作业服务。
下面的C#扩展方法应该有助于为给定的JobService子类创建一个ComponentName:

点击(此处)折叠或打开

  1. public static ComponentName GetComponentNameForJob<T>(this Context context) where T : JobService, new()
  2. {
  3.    Class javaClass = Class.FromType(typeof(T));
  4.    return new ComponentName(context, javaClass);
  5. }
创建JobInfo后,应用程序可以安排一项工作。 此代码片段将获得对JobScheduler服务的引用,并要求它安排在jobInfo对象中标识的作业:

点击(此处)折叠或打开

  1. JobScheduler jobScheduler = (JobScheduler)GetSystemService(JobSchedulerService);
  2. int result = jobScheduler.Schedule(jobInfo);
  3. if (result == JobScheduler.ResultSuccess)
  4. {
  5.    // The job was scheduled.
  6. }
  7. else
  8. {
  9.    // Couldn't schedule the job.
  10. }
应用程序也可以将参数传递给服务,方法是将其打包到Bundle中,然后调用JobInfo.SetExtras方法。 Bundle包含在调用OnStartJob时传递给JobService的JobParameters对象中。 例如,这段代码将传递一个值给作业:

点击(此处)折叠或打开

  1. // Bundle up parameters
  2. var jobParameters = new PersistableBundle();
  3. extras.PutLong("some_long_value", 10L);
  4.  
  5. // Put the Bundle with the parameters into the jobInfo.
  6. JobInfo.Builder builder = new JobInfo.Builder(context, component)
  7.                                      .SetExtras(extras);
  8. JobInfo jobInfo = builder.Build();
要访问此值,JobService应读取JobParameter对象上的.Extras属性:

点击(此处)折叠或打开

  1. public override bool OnStartJob(JobParameters jobParams)
  2. {
  3.    long theValue = jobParams.Extras.GetLong("some_long_value", -1);
  4.  
  5.    // Job does something with the value.
  6. }

最后,当一个JobService完成了它的工作(不管工作在哪个线程上),它应该调用它自己的JobFinished()方法。 调用此方法非常重要,因为它告诉JobScheduler工作已经完成,并且首先释放为JobService获取的任何唤醒锁定是安全的。 此图说明了JobService方法如何相互关联以及如何使用它们:



The relationship of JobService method calls.

现在您已经看到了JobScheduler API的基础知识,请尝试在您的Xamarin.Android应用程序中使用它来替换在后台服务中完成的任务。 这是一个很好的机会,可以增强用户对应用程序的体验,并一次性更新到Android Oreo 8.0!
您可以在GitHub上找到一个显示JobScheduler API的小示例。 该示例计算作业中的斐波那契数字,然后将该数字传递回活动。

上一篇:【Xamarin.Forms】XAML命名空间——将XAML名称空间声明为引用类型
下一篇:【Xamarin.Forms】使用Xamarin.Forms的企业应用程序模式(电子书)——目录索引