4、WorkRequest详解:OneTimeWorkRequest与PeriodicWorkRequest、WorkRequest的构建器模式、设置任务ID与标签、任务约束条件入门
好,咱们今天来聊聊 WorkRequest。说实话,这是整个 WorkManager 里最核心的概念之一。你想想看,你要让系统帮你干活,总得告诉它「干什么活、什么时候干、有什么要求」吧?WorkRequest 就是干这个的。
我个人习惯把 WorkRequest 理解成「任务订单」。你写好 Worker(干活的人),然后通过 WorkRequest 把订单下给系统。系统拿到订单后,会根据你设置的约束条件,在合适的时机安排执行。
两种 WorkRequest:一次性 vs 周期性
WorkManager 提供了两种任务类型,说白了就是:干一次 和 反复干。
| 类型 | 类名 | 适用场景 |
|---|---|---|
| 一次性任务 | OneTimeWorkRequest | 上传日志、发送通知、数据同步一次 |
| 周期性任务 | PeriodicWorkRequest | 定期清理缓存、每日统计上报、心跳检测 |
我在项目中遇到过这样一个坑:有个同事把「用户退出登录时清除本地缓存」做成了 PeriodicWorkRequest。结果用户每次退出,系统都以为要定期执行,搞得缓存清了一遍又一遍。嗯,这里要注意——一次性任务就用 OneTimeWorkRequest,别图省事混着用。
构建器模式:链式调用真香
WorkRequest 的构建器模式,我个人觉得是 Android 里设计得最舒服的 API 之一。你不需要记住一堆参数的顺序,直接链式调用就行。
// 一次性任务
val uploadWork = OneTimeWorkRequestBuilder<UploadWorker>()
.setInputData(workDataOf("key" to "value"))
.addTag("upload")
.build()
// 周期性任务(最短间隔15分钟)
val cleanWork = PeriodicWorkRequestBuilder<CleanWorker>(
15, TimeUnit.MINUTES
)
.setConstraints(constraints)
.addTag("clean")
.build()
你看,代码读起来就像在说「我要一个上传任务,给它传点数据,打个标签,好了」。这就是构建器模式的好处——可读性强,不容易出错。
任务 ID:给你的任务一个身份证
每个 WorkRequest 创建时都会自动生成一个 UUID。但说实话,UUID 那串东西谁记得住?所以 WorkManager 允许你自定义 ID。
val customId = UUID.fromString("a1b2c3d4-e5f6-7890-abcd-ef1234567890")
val work = OneTimeWorkRequestBuilder<MyWorker>()
.setId(customId)
.build()
为什么要自定义 ID?我举个例子。你有个「每日签到」的任务,如果每次生成随机 ID,你就没法判断这个任务是不是已经存在了。用固定 ID,你可以通过 WorkManager.getWorkInfoById() 随时查询状态。
标签:给任务分组管理
标签就像给任务贴的便签。你可以给多个任务贴上同一个标签,然后一次性操作它们。
// 给任务贴标签
val workA = OneTimeWorkRequestBuilder<WorkerA>()
.addTag("sync_group")
.build()
val workB = OneTimeWorkRequestBuilder<WorkerB>()
.addTag("sync_group")
.build()
// 取消整个组
WorkManager.getInstance(context)
.cancelAllWorkByTag("sync_group")
我曾经接手过一个项目,里面十几个任务都是单独取消的,代码写得又臭又长。后来我全部加上标签,一行代码就能取消一组任务。标签这东西,前期规划好,后期维护能省不少事。
任务约束条件入门
约束条件,说白了就是「什么时候才干活」。你不想在用户刷抖音的时候突然跑个上传任务吧?也不想在电量只剩 5% 的时候做视频压缩吧?
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED) // 需要网络
.setRequiresBatteryNotLow(true) // 电量不低
.setRequiresCharging(true) // 正在充电
.setRequiresStorageNotLow(true) // 存储空间充足
.setRequiresDeviceIdle(true) // 设备空闲(API 23+)
.build()
val work = OneTimeWorkRequestBuilder<BackupWorker>()
.setConstraints(constraints)
.build()
这里有个细节我想强调一下:约束条件是「与」的关系。也就是说,所有条件都满足时,任务才会执行。你设了需要网络 + 需要充电,那手机插着电但没网,任务照样不跑。
嗯,说到这我想起一个真实案例。有个同事给日志上传任务加了 setRequiresDeviceIdle(true),结果用户手机从来没空闲过(一直在刷视频),日志攒了一个月都没传上去。后来我建议他去掉这个约束,或者加个超时兜底策略,问题才解决。
知识体系总览
下面这张图是我自己整理的,把 WorkRequest 的核心知识点串了起来。你看一遍应该就能有个整体印象。
从图上你能看出来,WorkRequest 就两大分支。但不管哪种类型,构建器模式、ID、标签、约束条件这些公共特性都是一样的。学透这些,你就能应付绝大多数后台任务场景了。
好了,这一节的内容就到这。记住一句话:WorkRequest 是任务订单,Worker 是干活的人,约束条件是干活的前提。把这几个概念理清楚,后面的内容学起来就轻松多了。