后台与启动
后台与启动 · androidx.work
WorkManager:可延迟的保证执行Work 2.12.0-beta01
用 Worker、Constraints、唯一工作、周期工作和结果语义设计后台任务。
最后更新 2026-08-01
复制即用:一次性任务
class UploadWorker(
appContext: Context,
params: WorkerParameters,
) : CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result = try {
uploadPendingFiles()
Result.success()
} catch (error: IOException) {
Result.retry()
}
}
val request = OneTimeWorkRequestBuilder<UploadWorker>()
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
)
.build()
WorkManager.getInstance(context).enqueueUniqueWork(
"pending-upload",
ExistingWorkPolicy.KEEP,
request,
)结果语义
| Result | 含义 |
|---|---|
Result.success() | 完成(不重试) |
Result.failure() | 终止该链 |
Result.retry() | 按退避策略再次调度 |
幂等:Worker 可能重试或进程重建后重新运行——业务操作必须幂等(重复执行结果一致)。
Constraints:运行条件
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.setRequiresDeviceIdle(true)
.build()| 条件 | 说明 |
|---|---|
NetworkType | CONNECTED / UNMETERED / NOT_ROAMING |
RequiresCharging | 充电时 |
RequiresBatteryNotLow | 电量充足 |
RequiresDeviceIdle | 设备空闲 |
边界:Constraints 是运行条件,不是立即执行承诺——不满足时任务排队等待,不是立刻跑。
任务类型选择
| 类型 | 场景 |
|---|---|
| 一次性(OneTimeWorkRequest) | 上传、同步、清理 |
| 周期(PeriodicWorkRequest) | 定期同步(最短 15 分钟) |
| 链式(beginWith → then) | 多步骤流水线 |
// 周期任务
val periodic = PeriodicWorkRequestBuilder<SyncWorker>(6, TimeUnit.HOURS)
.build()
// 链式
WorkManager.getInstance(context)
.beginWith(OneTimeWorkRequestBuilder<DownloadWorker>().build())
.then(OneTimeWorkRequestBuilder<ProcessWorker>().build())
.enqueue()唯一工作:去重策略
WorkManager.getInstance(context).enqueueUniqueWork(
"sync-task",
ExistingWorkPolicy.KEEP, // 已有则忽略新请求
request,
)| Policy | 行为 |
|---|---|
KEEP | 已有进行中/排队则忽略 |
REPLACE | 取消旧的,替换新的 |
APPEND | 追加到已有任务之后 |
按业务语义选择;不要用随机名称绕开重复问题。
观察状态
WorkManager.getInstance(context)
.getWorkInfoByIdLiveData(request.id)
.observe(owner) { info ->
when (info?.state) {
WorkInfo.State.ENQUEUED -> {}
WorkInfo.State.RUNNING -> {}
WorkInfo.State.SUCCEEDED -> {}
WorkInfo.State.FAILED -> {}
WorkInfo.State.CANCELLED -> {}
}
}什么不该用 WorkManager
- 用户正在等待的短操作(登录、支付):用协程/线程。
- 精确闹钟:
AlarmManager(setExactAndAllowWhileIdle)。 - 持续媒体播放:
MediaSession+ 前台服务。 - 长时前台任务:前台服务。
WorkManager 适合可延迟、需要保证最终执行的后台任务。
常见陷阱
- 非幂等:重试/进程重建后重复执行出错。
- 短任务用 WorkManager:延迟不可控,用户等不了。
- 结果丢:不观察 WorkInfo 不知道成功失败。
- 周期最短 15 分钟:想更快用别的机制。
- 随机工作名:去重失效。
复制即用
class SyncWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
val input = inputData.getString("url") ?: return Result.failure()
return try {
syncFrom(input)
Result.success()
} catch (e: Exception) {
if (runAttemptCount < 3) Result.retry() else Result.failure()
}
}
}要点
success/failure/retry三种结果;任务必须幂等。- Constraints 是条件非承诺;短任务/闹钟/媒体不用 WorkManager。
- 唯一工作 + 业务语义选 Policy;链式任务用 beginWith → then。
- 观察 WorkInfo 状态才知道结果。