Administrator
发布于 2026-08-25 / 13 阅读
0
0

系列文章《Android 工程师的 100 篇进阶笔记》第 21 篇:WorkManager:后台任务的一站式解决方案

Android 后台限制越来越严。Doze、App Standby、后台启动限制,让 AlarmManager 和 Service 不再是首选。复杂后台任务,现在基本交给 WorkManager。


一、WorkManager 能解决什么问题

场景

旧方案

WorkManager 方案

定时同步

AlarmManager + Service

PeriodicWorkRequest

上传日志

IntentService

OneTimeWorkRequest

链式任务

手写状态机

WorkContinuation

带约束执行

手动判断

Constraints

WorkManager 适合可延迟、有保证执行的任务。即时任务请用 Foreground Service。


二、一次性任务与周期性任务

// 一次性
val uploadWork = OneTimeWorkRequestBuilder<UploadWorker>()
    .setConstraints(
        Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .setRequiresBatteryNotLow(true)
            .build()
    )
    .build()

WorkManager.getInstance(context).enqueue(uploadWork)

// 周期性,最小间隔 15 分钟
val syncWork = PeriodicWorkRequestBuilder<SyncWorker>(1, TimeUnit.HOURS)
    .setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.UNMETERED).build())
    .build()

三、Worker 怎么写

class UploadWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, params) {
    override fun doWork(): Result {
        return try {
            uploadFiles()
            Result.success()
        } catch (e: Exception) {
            Result.retry()
        }
    }
}

如果需要进度更新或异步操作,用 CoroutineWorker 或 ListenableWorker。

class SyncWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) {
    override suspend fun doWork(): Result {
        setProgress(workDataOf("progress" to 0))
        // ...
        return Result.success()
    }
}

四、任务链与重试策略

WorkManager.getInstance(context)
    .beginWith(cleanupWork)
    .then(compressWork)
    .then(uploadWork)
    .enqueue()

支持复杂的 DAG 结构。重试用 setBackoffCriteria:

OneTimeWorkRequestBuilder<UploadWorker>()
    .setBackoffCriteria(
        BackoffPolicy.EXPONENTIAL,
        OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
        TimeUnit.MILLISECONDS
    )
    .build()

五、观察任务状态

WorkManager.getInstance(context)
    .getWorkInfoByIdLiveData(uploadWork.id)
    .observe(owner) { info ->
        if (info?.state == WorkInfo.State.SUCCEEDED) {
            // 完成
        }
    }

也可以用 Flow:getWorkInfoByIdFlow(id)。


小结

  1. WorkManager 适合可延迟、有保证的后台任务

  2. 即时任务不要用 WorkManager,用前台 Service

  3. Constraints 可以省掉一堆手动判断

  4. 任务链 + 重试机制能覆盖大多数后台同步需求

下一篇,我们回到 UI 适配,聊聊 WindowInsets、ConstraintLayout 与 Compose 的响应式布局。


参考阅读

引用链接

[1]WorkManager 官方文档: https://developer.android.com/topic/libraries/architecture/workmanager

[2]Background work on Android: https://developer.android.com/guide/background


评论