核心特点
- 适合需要保证执行的延期/周期性任务。
- 支持电量、网络、存储等约束。
- 提供任务链、唯一任务与重试策略。
基础配置
dependencies {
implementation("androidx.work:work-runtime-ktx:2.9.0")
}
class App : Application(), Configuration.Provider {
override fun getWorkManagerConfiguration(): Configuration {
return Configuration.Builder()
.setMinimumLoggingLevel(Log.INFO)
.build()
}
}
定义 Worker
class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
repository.sync()
Result.success()
} catch (e: IOException) {
Result.retry()
}
}
}
约束与调度
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.build()
val workRequest = OneTimeWorkRequestBuilder<SyncWorker>()
.setConstraints(constraints)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30.seconds)
.build()
WorkManager.getInstance(context).enqueueUniqueWork(
"sync", ExistingWorkPolicy.KEEP, workRequest
)
链式任务
WorkManager.getInstance(context)
.beginWith(OneTimeWorkRequestBuilder<UploadWorker>().build())
.then(OneTimeWorkRequestBuilder<NotifyWorker>().build())
.enqueue()
- 使用
WorkContinuation构建串行或并行任务链。
周期性任务
val periodicWork = PeriodicWorkRequestBuilder<SyncWorker>(12, TimeUnit.HOURS)
.setConstraints(constraints)
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"periodic_sync", ExistingPeriodicWorkPolicy.UPDATE, periodicWork
)
输入输出数据
val request = OneTimeWorkRequestBuilder<UploadWorker>()
.setInputData(workDataOf("filePath" to filePath))
.build()
class UploadWorker(...): CoroutineWorker(...) {
override suspend fun doWork(): Result {
val filePath = inputData.getString("filePath") ?: return Result.failure()
val success = uploader.upload(filePath)
return if (success) Result.success(workDataOf("url" to "https://...")) else Result.retry()
}
}
与 Hilt 集成
@HiltWorker
class SyncWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted params: WorkerParameters,
private val repository: SyncRepository
) : CoroutineWorker(context, params) { ... }
// 在 Application 中提供 HiltWorkerFactory(androidx.hilt:hilt-work 的公开 API)
@HiltAndroidApp
class App : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
override val workManagerConfiguration: Configuration
get() = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
运行状态监听
WorkManager.getInstance(context)
.getWorkInfosForUniqueWorkLiveData("sync")
.observe(lifecycleOwner) { workInfos ->
workInfos.firstOrNull()?.let { info ->
when (info.state) {
WorkInfo.State.SUCCEEDED -> showToast("Sync success")
WorkInfo.State.FAILED -> showToast("Sync failed")
else -> Unit
}
}
}
常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 周期任务不执行 | 周期 < 15 分钟或约束不满足 | 确保最小周期大于 15 分钟,检查约束 |
| 任务重复 | 未设置唯一工作策略 | 使用 enqueueUniqueWork 或 KEEP 策略 |
| 资源占用高 | 过多任务并行 | 通过 WorkManager.initialize 设置最大并行数 |
实战案例:国内 ROM 是 WorkManager 的”最终考官”
WorkManager 的设计很优雅:OneTimeWorkRequest / PeriodicWorkRequest + Constraints(要充电、要 WiFi),系统替你选 JobScheduler 还是 AlarmManager。但这套在国内 ROM 上要打折扣——小米/华为/OV 的后台管理比 AOSP 激进得多,WorkManager 的任务经常被”优化”掉。
我在 Flutter 侧做后台任务(比如定时同步)时,Android 端走的是 workmanager 插件(底层就是 WorkManager),同样被 ROM 杀。实战里必做的三件事:
- 引导用户加白名单:跳到电池优化设置页(
ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS),话术要直白——“不加白名单,消息推送会延迟”。 - 别用精确周期:
PeriodicWorkRequest的最小间隔 15 分钟,且不保证准时。需要准时的场景(如闹钟)走setExact+ 前台服务,别指望 WorkManager。 - WorkManager 3.x 开始支持跨进程和更细的约束,新项目直接用最新版,老项目的
WorkManager 2.x迁移成本不高,值得升。
一句话:WorkManager 解决的是”AOSP 的标准问题”,国内上线还要解决”ROM 的现实问题”。两手都要抓。
参考:Android 官方文档《WorkManager》;《后台任务指南》
总结
- WorkManager 是保障型后台任务首选,结合协程可编写可读的异步逻辑。
- 注意唯一工作策略、约束配置,与应用生命周期保持一致。
- 搭配 Hilt、Flow 等组件能实现状态追踪与依赖注入,提升整体可维护性。
