Android WorkManager 可靠后台任务
Android WorkManager 可靠后台任务
摘要:上传日志、同步待办和清理缓存等工作可能因进程退出或网络变化而中断。WorkManager 适合执行需要可靠完成的可延迟任务。本文介绍 Worker、约束、重试、唯一任务和任务链的设计方式。
一、先选对后台执行方式
后台任务并非都应该用同一个 API。WorkManager 面向可延迟、需要系统在条件满足时尽力执行的工作;前台服务适用于用户能感知且需要持续运行的任务;精确闹钟则用于用户明确要求精确时间触发的场景。WorkManager 不保证在指定秒数内执行,也不应当被当作精确计时器。
二、定义一次性 Worker
CoroutineWorker 适合在 Kotlin 项目中运行挂起操作:
class UploadWorker(
appContext: Context,
params: WorkerParameters,
private val repository: UploadRepository
) : CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
val batchId = inputData.getString("batch_id")
?: return Result.failure()
return try {
repository.uploadBatch(batchId)
Result.success()
} catch (cancelled: CancellationException) {
throw cancelled
} catch (error: IOException) {
Result.retry()
} catch (error: Exception) {
Result.failure()
}
}
}
success 表示工作已完成,retry 表示暂时性失败可稍后重试,failure 表示不应自动继续。输入数据适合放小型标识或参数,不适合携带大型对象。
生产项目可通过 WorkerFactory 或依赖注入集成工厂,为 Worker 提供 Repository。不要依赖系统反射去构造带自定义参数的 Worker。
三、为任务添加约束
例如只有网络可用且设备正在充电时才上传:
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresCharging(true)
.build()
val request = OneTimeWorkRequestBuilder<UploadWorker>()
.setInputData(workDataOf("batch_id" to batchId))
.setConstraints(constraints)
.setBackoffCriteria(
BackoffPolicy.EXPONENTIAL,
30,
TimeUnit.SECONDS
)
.build()
约束是在执行前提,不是执行时间保证。网络或电量条件变化后,系统可能暂停任务,稍后再继续。
四、避免重复排队
相同业务目标可能被按钮连点、进程重启或多处调用重复提交。使用唯一工作名称可以明确新任务与已有任务的关系:
WorkManager.getInstance(context).enqueueUniqueWork(
"upload-$batchId",
ExistingWorkPolicy.KEEP,
request
)
KEEP 保留正在运行或等待中的工作;REPLACE 用新工作替换已有工作;需要串行执行时可考虑 APPEND。选择策略前要先定义业务语义:重复提交是忽略、替换还是排队处理。
唯一工作可以避免队列重复,但服务端仍应支持幂等操作。任务可能在服务端完成后、客户端记录成功前被重试。
五、组织有依赖关系的任务
若上传必须先压缩文件,再传输,最后提交索引,可以用工作链表达依赖:
val compress = OneTimeWorkRequestBuilder<CompressWorker>().build()
val upload = OneTimeWorkRequestBuilder<UploadWorker>().build()
val index = OneTimeWorkRequestBuilder<IndexWorker>().build()
WorkManager.getInstance(context)
.beginUniqueWork("archive-$archiveId", ExistingWorkPolicy.KEEP, compress)
.then(upload)
.then(index)
.enqueue()
链路会按依赖关系推进。失败策略也要纳入设计,例如压缩永久失败后是否允许后续步骤继续,通常应由业务状态明确表达。
六、周期性任务的边界
周期任务适合定期检查或汇总工作,但系统会根据电量、待机和其他限制调整实际运行时间。周期间隔有系统规定的下限,也不保证准点。若工作只需在应用打开时刷新,不要为了“每隔一小段时间”强行加入后台周期任务。
七、观察、取消与调试
可通过任务 ID 或唯一名称观察 WorkInfo,读取状态、进度和输出数据。进度适合表示粗粒度阶段,不应频繁写入。用户主动取消时,同时停止任务并更新业务状态;Worker 应定期检查取消或调用可取消的挂起 API。
开发调试时查看任务状态转换、约束是否满足、重试次数和输入输出数据。不同设备厂商的后台限制可能不同,关键流程应在真实设备和进程重启场景中验证。
八、常见问题
- 不要在 Worker 中做无限循环;一次执行应有明确边界。
- 重试只适合暂时性故障,参数错误等永久问题应失败并记录原因。
- Worker 可能重复执行,服务端写入要考虑幂等。
- 大文件不放进 Data,改用本地文件标识并管理文件生命周期。
- 需要面向用户持续展示的长任务,应重新评估前台服务等机制。
九、总结
WorkManager 提供持久化排队、条件约束、重试和链式依赖,适合可靠但不要求准点的后台工作。把每项工作设计成可取消、可重试且幂等的小步骤,再明确唯一任务策略,能够显著降低弱网和进程回收带来的数据问题。
- 点赞
- 收藏
- 关注作者
评论(0)