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还要求,必须在前一个后台任务运行成功之后,下一个后台任务才会运行,也就是说,如果某个后台任务运行失败了,或者取消了,那么接下来的后台任务就都得不到运行了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,635评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,543评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,083评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,640评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,640评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,262评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,833评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,736评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,280评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,369评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,503评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,185评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,870评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,340评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,460评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,909评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,512评论 2 359

推荐阅读更多精彩内容

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