WorkManager

  • 基本概念

WorkManager很适合用于处理一些要求定时执行的任务,它可以根据操作系统的版本自动选择底层是使用AlarmManager实现还是JobScheduler实现,从而降低我们的使用成本。另外,它还支持周期性任务、链式任务处理等功能,是一个非常强大的工具。WorkManager只是一个处理定时任务的工具,它可以保证即使在应用退出甚至手机重启的情况下,之前注册的任务仍然将会得到执行,因此,WorkManager很适合用于执行一些定期和服务器进行交互的任务,比如周期性地同步数据等等。

  • WorkManager的基本用法
  • 依赖
    implementation 'androidx.work:work-runtime:2.2.0'
  • 主要分为三步
  1. 定义一个后台任务,并实现具体的任务逻辑
  2. 配置该后台任务的运行条件和约束信息,并构建后台任务请求
  3. 将该后台任务请求传入WorkManagerenqueue()方法中,系统会在合适的时间运行
  • 第一步:定义一个后台任务,这里创建一个SimpleWorker类
class SimpleWorker(context: Context, params: WorkerParameters): Worker(context, params) {
    
    override fun doWork(): Result {
        Log.e("SimpleWorker", "do work in simpleWorker")
        return Result.success()
    }

}

后台任务的写法非常固定,首先每一个后台任务都必须继承自Worker类,并调用唯一的构造函数,然后重写父类的doWork()方法,在这个方法里编写具体的后台任务逻辑。doWork()方法不会运行在主线程中,另外它要求返回一个Result对象,用于表示任务的执行结果成功返回Result.success()失败返回Result.failure(),还有一个Result.retry(),它也代表着失败,只是可以结合WorkRequest.BuildersetBackoffCriteria()方法来重新执行任务

  • 第二步:配置该后台任务的运行条件和约束信息,这里只进行最基本配置
    val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()

OneTimeWorkRequest.BuilderWorkRequest.Builder的子类,用于构建单次运行的后台任务请求WorkRequest.Builder还有另外一个子类,PeriodicWorkRequest.Builder,可用于构建周期性运行的后台任务请求,但是为了降低设备性能消耗,PeriodicWorkRequest.Builder构造函数中传入的运行周期间隔不能短于15分钟,如下:
val request = PeriodicWorkRequest.Builder(SimpleWorker::class.java, 15, TimeUnit.MINUTES).build()

  • 第三步:将构建出的后台任务请求传入WorkManagerenqueue()方法中,系统就会在合适的时间去运行了
    WorkManager.getInstance(context).enqueue(request)
        doWorkBtn.setOnClickListener { 
            val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()
            WorkManager.getInstance(this).enqueue(request)
        }
  • 使用WorkManager处理复杂的任务
  • 让后台任务延迟指定时间后运行,只需借助setInitialDelay()方法
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
        .setInitialDelay(5, TimeUnit.MINUTES)
        .build()

这就表示我们希望让SimpleWorker这个后台任务在5分钟后运行,你可以自由地选择时间的单位,毫秒、秒、分钟、小时、天都可以。

  • 给后台任务请求添加标签,以便取消任务
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
        .setInitialDelay(5, TimeUnit.MINUTES)
        .addTag("simple")
        .build()
  • 通过标签取消后台任务请求
workManager.getInstance(this).cancelAllWorkByTag("simple")
  • 当然,即使没有标签,我们也可以通过id来取消后台任务请求
workManager.getInstance(this).cancelWorkById(request.id)
  • 但是,使用id只能取消单个后台任务请求,而使用标签的话,则可以将同一标签名的所有后台任务请求全部取消
  • 除此之外,我们也可以使用如下代码来一次性取消所有后台任务请求
workManager.getInstance(this).cancelAllWork()
  • 如果后台任务的doWork()方法中返回了Result.retry(),那么是可以结合setBackoffCriteria()方法来重新执行任务的
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
        .setInitialDelay(5, TimeUnit.MINUTES)
        .addTag("simple")
        .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS)
        .build()

setBackoffCriteria()方法接收三个参数:第二个和第三个参数用于指定在多久之后重新执行任务,时间最短不能少于10秒钟;第一个参数则用于指定如果任务再次执行失败,下次重试的时间应该以什么样的形式延迟;假如任务一直执行失败,不断地重新执行似乎并没有什么意义,只会徒增设备的性能消耗,而随着失败次数的增多,下次重试的时间也应该进行适当的延迟,这才是更加合理的机制,第一个参数的可选值有两种,分别是LINEAREXPONENTIAL前者代表下次重试时间以线性的方式延迟,后者代表下次重试时间以指数的方式延迟。

  • 我们可以使用如下代码对后台任务的运行结果进行监听
WorkManager.getInstance(this)
        .getWorkInfoByIdLiveData(request.id)
        .observe(this){ workInfo ->
            if(workInfo.state == WorkInfo.State.SUCCESS){

            }else if(WorkInfo.state == WorkInfo.State.FAILED){

            }
        }

这里调用getWorkInfoByIdLiveData()方法,并传入后台任务请求的id,会返回一个LiveData对象,然后调用它的observe()方法来观察数据变化了,以此监听后台任务的运行结果。也可以调用getWorkInfoByTagLiveData()方法,监听同一标签名下所有后台任务请求的运行结果,用法是差不多的。

  • 再来看一下WorkManager中比较有特色的一个功能--链式任务

假设这里定义了三个独立的后台任务:同步数据压缩数据上传数据,现在我们想要实现先同步、再压缩、最后上传的功能,就可以借助链式任务来实现

val sync = ...
val compress = ...
val upload = ...
WorkManager.getInstance(this)
        .beginWith(sync)
        .then(compress)
        .then(upload)
        .enqueue()

beginWith()方法用于开启一个链式任务,至于后面要接上什么样的后台任务,只需要使用then()方法来连接即可。另外,WorkManager还要求,必须在前一个后台任务运行成功之后,下一个后台任务才会运行,也就是说,如果某个后台任务运行失败了,或者取消了,那么接下来的后台任务就都得不到运行了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1、概述 在 I / O '18中,Google发布了Android Jetpack。它是一组库,工具和架构指南,...
    高丕基阅读 7,594评论 1 12
  • WorkManager WorkManager很适合用于处理一些要求定时执行的任务,它可以根据操作系统的版本自动选...
    0246eafe46bd阅读 576评论 0 0
  • WorkManager架构组件是用来管理后台工作任务。这个时候你可能会奇怪了Android不是已经 有很多管...
    tuacy阅读 6,593评论 4 14
  • 前言 前面的内容中我们已经介绍了很多Jetpack中的架构组件,可以说每一种组件的出现都是为了更好的解决现在存在的...
    rivenlee阅读 815评论 0 1
  • 背景:通常我们在开发过程中处理后台任务的时候可能是自己维系一个线程池或者通过一个后台任务来完成我们的工作,然后对于...
    o蚂蚁上树o阅读 1,824评论 0 50