Android Jetpack 组件之 WorkManager(Kotlin)

一、简介

WorkManager 用于处理 Android 后台任务。我们只需要设置好任务内容、何时执行,剩下的工作就可以完全交给系统处理。它会自动向下兼容,在不同的 Android 版本上采用不同的实现方案。

由于是交给系统调度的,它可以保证应用退出甚至手机重启后,任务依然能够得到执行。WorkManager 很适合执行一些定期和服务器交互的任务,比如周期性的同步数据等等。并且,WorkManager 还支持周期性任务、链式任务。

需要注意的是,WorkManager 不能保证任务一定能够准时执行,这是因为系统为了减少电量消耗,会将触发事件临近的几个任务放在一起执行,以减少 CPU 被唤醒的次数,延长电池使用时间。

另外,在国产手机上 WorkManager 可能无法正常运行,这是因为绝大多数手机厂商定制 Android 系统时,会添加一个“一键关闭”的功能,这样被杀死后的应用程序,既无法接收广播,也不能运行 WorkManager 的后台任务。国产手机增加此功能也是迫于无奈,主要是因为市面上有太多的恶意应用想要霸占后台。所以,我们在国产手机上不要使用 WorkManager 去实现核心功能。

二、导入

在 app/build.gradle 中添加依赖:

implementation 'androidx.work:work-runtime:2.3.2'

三、基本使用

WorkManager 的用法分为三步:

  • 定义一个后台任务
  • 配置任务运行条件
  • 将任务传给 WorkManager

3.1 定义后台任务

创建一个 SimpleWorker 类,继承自 Worker:

class SimpleWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        Log.d("~~~", "do something")
        return Result.success()
    }
}

在 doWork 方法中实现任务逻辑,返回的 Result 是一个系统类,主要有三个方法供我们使用:

  • Result.success() 表示任务执行成功
  • Result.failure() 表示任务执行失败
  • Result.retry() 表示任务需要重试。这个方法需要配合任务重试配置一起使用

3.2 配置任务运行条件

3.2.1 只需执行一次的任务

使用 OneTimeWorkRequest 构建只需执行一次的任务

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()

3.2.2 周期性执行的任务

使用 PeriodicWorkRequest 构建周期性执行的任务

val request = PeriodicWorkRequest.Builder(SimpleWorker::class.java, 15, TimeUnit.MINUTES).build()

为了减少耗电量,PeriodicWorkRequest 要求任务执行周期不得短于十五分钟,查看源码可以发现,如果传入的值短于十五分钟,系统会打印一条警告,然后自动将周期设置成十五分钟:

public static final long MIN_PERIODIC_INTERVAL_MILLIS = 15 * 60 * 1000L; // 15 minutes.

/**
 * Sets the periodic interval for this unit of work.
 *
 * @param intervalDuration The interval in milliseconds
 */
public void setPeriodic(long intervalDuration) {
    if (intervalDuration < MIN_PERIODIC_INTERVAL_MILLIS) {
        Logger.get().warning(TAG, String.format(
                "Interval duration lesser than minimum allowed value; Changed to %s",
                MIN_PERIODIC_INTERVAL_MILLIS));
        intervalDuration = MIN_PERIODIC_INTERVAL_MILLIS;
    }
    setPeriodic(intervalDuration, intervalDuration);
}

3.3 将任务传给 WorkManager

WorkManager.getInstance(this).enqueue(request)

这就是 WorkManager 的基本使用。

四、高级配置

4.1 设置任务延迟执行

通过 setInitialDelay 方法设置延迟时间

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
   .setInitialDelay(5, TimeUnit.MINUTES)
   .build()

4.2 给任务添加标签

通过 addTag 方法添加标签:

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .addTag("simple")
    .build()

添加标签的作用是,方便我们根据标签取消任务。

4.3 取消任务

4.3.1 根据标签取消任务

WorkManager.getInstance(this).cancelAllWorkByTag("simple")

4.3.2 根据 request 的 id 取消任务

WorkManager.getInstance(this).cancelWorkById(request.id)

4.3.3 取消所有任务

WorkManager.getInstance(this).cancelAllWork()

4.4 任务重试

通过 setBackoffCriteria 配置任务重试:

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS)
    .build()

前文说到,Result.retry() 表示任务需要重试,这个方法需要配合任务重试配置一起使用。任务重试配置就是指这个 setBackoffCriteria 方法,它传入了三个值,第二个值和第三个值表示重试时间配置。第一个值表示重试延迟的形式,有两个值可供选择:

  • BackoffPolicy.LINEAR 重试时间每次呈线性增长,按照此例中的配置,每次重试时间就是 10s,20s,30s,40s…
  • BackoffPolicy.EXPONENTIAL 重试时间每次呈指数级增长,按照此例中的配置,每次重试时间就是 10s,20s,40s,80s…

4.5 监听任务结果

WorkManager.getInstance(this).getWorkInfoByIdLiveData(request.id).observe(this) {
    Log.d("~~~", "state = ${it.state}, tags = ${it.tags.toList()}")
    when (it.state) {
        WorkInfo.State.SUCCEEDED -> Log.d("~~~", "success")
        WorkInfo.State.FAILED -> Log.d("~~~", "fail")
        WorkInfo.State.RUNNING -> Log.d("~~~", "running")
        WorkInfo.State.ENQUEUED -> Log.d("~~~", "enqueued")
        WorkInfo.State.CANCELLED -> Log.d("~~~", "cancelled")
        WorkInfo.State.BLOCKED -> Log.d("~~~", "blocked")
    }
}

首先通过 getWorkInfoByIdLiveData 获得任务信息的 LiveData<WorkInfo> 数据,然后观察此数据即可。也可以通过 getWorkInfosByTagLiveData 获得相同 Tag 的 LiveData<List<WorkInfo>>,观察这个任务信息列表。通过 WorkInfo 的 getState 方法获取任务状态,主要用到的状态有 WorkInfo.State.SUCCEEDEDWorkInfo.State.FAILED,标志着任务的成功和失败。

4.6 传递数据

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .setInputData(Data.Builder().apply {
        putString("key", "value")
    }.build())
    .build()

SimpleWorker 类中读取此数据:

inputData.getString("key")

4.7 链式任务

val first = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .build()
val second = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .build()
val third = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .build()
WorkManager.getInstance(this)
    .beginWith(first)
    .then(second)
    .then(third)
    .enqueue()

通过 beginWith 发起链式任务,然后后缀 then 即可,任务会按照连接顺序依次执行。WorkManager 要求必须在上一个任务执行成功后,才会执行下一个任务。也就是说任何一个任务的失败都会导致链式任务的中断。

参考文章

《第一行代码》(第三版)- 第 13 章 13.6 WorkManager

### 回答1: Jetpack是一套基于Android开发语言Kotlin组件库,目的是帮助Android开发者快速构建健壮的、高效的应用程序。Jetpack架构组件从入门到精通是一本介绍Jetpack组件库的电子书,其内容向读者提供了Jetpack组件库的最基础的知识体系,以及对组件库的更高阶的实践知识和技能分享。 在读者学习这本电子书时,首先会学习到基本的Jetpack概念,并了解到如何使用各种工具来实现底层代码、布局和资源文件的编写。同时,电子书重点讲解了Jetpack组件库中最常用的组件,比如ViewModel、LiveData、Room、WorkManager等,它们各自的功能和用法,让读者熟知Jetpack组件的基本运作原理。读者还会学习如何将这些组件综合使用,以构造真正的应用程序。在内容的后半部分,电子书重点讲解了Jetpack在架构层面的设计,以及如何更有效的使用和管理组件库。 总之,Jetpack架构组件从入门到精通这本电子书非常适合想要学习Jetpack组件库的Android初学者和有一定开发经验的开发者,能够帮助他们快速掌握Jetpack组件库,以及提高软件的可扩展性和有效性。 ### 回答2: Jetpack架构组件是一组Android软件组件和库,通过这些组件和库,开发者可以更加轻松地开发应用程序,并提供高质量的用户体验。Jetpack架构组件包括众多不同的组件和库,这些组件和库都具有不同的用途和功能。对于开发者来说,学习Jetpack架构组件是非常重要的。 《jetpack架构组件从入门到精通 pdf》是一份针对Jetpack架构组件的学习资料。它是可以帮助开发者更好地理解和掌握Jetpack架构组件的重要手册。通过这份PDF文档,开发者可以学习到Jetpack架构组件的基本概念、用途和功能,并了解如何将这些组件和库应用到他们的应用程序开发中。 这份PDF文档涵盖了Jetpack架构组件的多个方面,包括ViewModel、LiveData、Data Binding、Room、Navigation、WorkManager等等。每个章节都包含了详细的介绍和具体的用例,从而帮助开发者更好地理解每个组件和库的用途和功能。 无论是初学者还是经验丰富的开发者,都可以从这份PDF文档中获益。它可以帮助初学者更轻松地入门Jetpack架构组件,并提供了有用的工具和技巧。对于经验丰富的开发者来说,这份PDF文档可以帮助他们更深入地了解Jetpack架构组件,并提供了一些高级技术和策略,以优化应用程序性能和用户体验。 总之,Jetpack架构组件从入门到精通的PDF文档是一份非常有价值的资源,它可以帮助开发者更好地理解和掌握Jetpack架构组件,从而更加轻松地开发高质量的Android应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值