0%

Android 架构组件之 WorkManager

简介

WorkManager 官方介绍是说用于在应用退出或者设备重启后还可以被系统调度来执行后台任务的组件。
主要功能直接摘抄官方文档

  • 最高向后兼容到 API 14
    • 在运行 API 23 及以上级别的设备上使用 JobScheduler
    • 在运行 API 14-22 的设备上结合使用 BroadcastReceiver 和 AlarmManager
  • 添加网络可用性或充电状态等工作约束
  • 调度一次性或周期性异步任务
  • 监控和管理计划任务
  • 将任务链接起来
  • 确保任务执行,即使应用或设备重启也同样执行任务
  • 遵循低电耗模式等省电功能

简单使用

添加依赖

1
2
3
4
5
def work_version = "2.3.4"

// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:$work_version"

WorkManager 对 lifecycle-service 和 sqlite-framework 有依赖,如果之前有引入需要注意版本。
三个步骤即可完成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 1)创建后台任务
class UploadWorker(appContext: Context, workerParams: WorkerParameters)
: Worker(appContext, workerParams) {

override fun doWork(): Result {
// Do the work here--in this case, upload the images.
uploadImages()
// Indicate whether the task finished successfully with the Result
return Result.success()
}
}

// 2)配置运行任务的方式和时间
val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.build()

// 3)将任务提交给系统
WorkManager.getInstance(myContext).enqueue(uploadWorkRequest)

配置任务分为一次性和周期性工作。周期性最短间隔是 15 分钟,和 JobScheduler 相同。

工作约束

配置工作的时候可以添加约束,例如指定仅在设备空闲且接通电源时运行。详细 API 可以看 Constraints.Builder,通过函数名称基础就能看出设置的含义。

其他

初始延迟

经过实验,就算是周期性的任务,在条件满足的时候也回立即执行,所以如果希望加入队列后等一段时间再执行的话,可以通过 setInitialDelay 设置一个初始延迟。

标记工作

您可以通过为任意 WorkRequest 对象分配标记字符串,按逻辑对任务进行分组。这样您就可以对使用特定标记的所有任务执行操作。

例如,WorkManager.cancelAllWorkByTag(String) 会取消使用特定标记的所有任务,可以用来取消周期性的任务。举例:

1
2
3
4
5
val cacheCleanupTask = OneTimeWorkRequestBuilder<CacheCleanupWorker>()
.setConstraints(constraints)
.addTag("cleanup")
.build()

定义任务的输入/输出

构造一个map类型的Data,通过WorkManager的setInputData()给Worker进行传输数据。如果需要把处理的结果进行返回,可以使用setOutputData()来完成,输出的结果一般可以用做下一个任务的输入。

国内 ROM 支持

经过试验,国内主流 ROM(小米、华为、Oppo、Vivo 等)在应用进程被杀死后,周期性任务就不会再被调用了。不过应用退后台熄屏的情况下,至少在一个小时内周期性任务还是会被调用的,测试时 2 个小时或者更长的时间也有遇到。

总结

WorkManager 的想法是好的,但是用户不太好控制,很容易被滥用吧。所以国内 ROM 做了限制也是情有可原。如果要做一些空闲时下载的功能又怕后台线程被杀掉的话,可以用 WorkManager 试试。

参考: