跳转到正文
YGJoon 技术博客

Android Kotlin WorkManager 后台任务策略

发布于:
·860 字 · 约 2 分钟·作者:
WorkManager 后台任务全攻略:约束调度、链式与周期任务、Hilt 注入 Worker,以及国内 ROM 保活这个绕不开的现实问题。
Android Kotlin WorkManager 后台任务策略文章封面
目录

核心特点

基础配置

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()

周期性任务

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 杀。实战里必做的三件事:

  1. 引导用户加白名单:跳到电池优化设置页(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS),话术要直白——“不加白名单,消息推送会延迟”。
  2. 别用精确周期:PeriodicWorkRequest 的最小间隔 15 分钟,且不保证准时。需要准时的场景(如闹钟)走 setExact + 前台服务,别指望 WorkManager。
  3. WorkManager 3.x 开始支持跨进程和更细的约束,新项目直接用最新版,老项目的 WorkManager 2.x 迁移成本不高,值得升。

一句话:WorkManager 解决的是”AOSP 的标准问题”,国内上线还要解决”ROM 的现实问题”。两手都要抓。

参考:Android 官方文档《WorkManager》;《后台任务指南》

总结

  1. WorkManager 是保障型后台任务首选,结合协程可编写可读的异步逻辑。
  2. 注意唯一工作策略、约束配置,与应用生命周期保持一致。
  3. 搭配 Hilt、Flow 等组件能实现状态追踪与依赖注入,提升整体可维护性。

分享这篇文章:


相关文章

上一篇
Android Kotlin Room 数据库进阶实践
下一篇
Android Kotlin 协程在实际项目中的应用