0Pricing
Android Academy · 课时

WorkManager 与后台任务

使用 WorkManager 安排有保障的后台工作。使用 OneTimeWorkRequest、PeriodicWorkRequest、约束、数据传递和工作链。

WorkManager 与后台任务 是 CoddyKit 上的免费 Android Academy 课时。 这是第 5 节课,共 6 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Android Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Android Academy 课程共包含 6 节课。

Android 中的后台任务

Android 会严格限制后台任务,以节省电量。在 WorkManager 出现之前,开发者使用过:

  • AsyncTask(已弃用)
  • AlarmManager(在设备重启或进入 Doze 模式后不可靠)
  • JobScheduler(API 复杂)
  • 服务(可能被终止,且不支持重试)

WorkManager 是处理可延迟且必须执行的后台任务的推荐方案。

什么是 WorkManager?

WorkManager 可以确保任务运行,即使应用被终止或设备重启也不例外。它可以:

  • 在设备重启后保留任务
  • 失败时自动重试
  • 支持约束条件(仅使用 WiFi、仅在充电时运行等)
  • 支持 API 14+
  • 通过 CoroutineWorker 与 Kotlin 协程集成

设置

将 WorkManager 添加到 app/build.gradle:

dependencies {
    implementation 'androidx.work:work-runtime-ktx:2.9.0'
}

创建 Worker

继承 CoroutineWorker 并实现 doWork()。返回 Result.success()、Result.failure() 或 Result.retry():

class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        return try {
            // This runs on a background coroutine
            val repo = UserRepository(applicationContext)
            repo.syncFromNetwork()
            Result.success()
        } catch (e: Exception) {
            if (runAttemptCount < 3) Result.retry()
            else Result.failure()
        }
    }
}

OneTimeWorkRequest

安排一次性任务并将其加入队列:

val syncWork = OneTimeWorkRequestBuilder<SyncWorker>()
    .setInitialDelay(10, TimeUnit.MINUTES)  // optional delay
    .build()

WorkManager.getInstance(context).enqueue(syncWork)

// With a unique name (prevents duplicates):
WorkManager.getInstance(context).enqueueUniqueWork(
    "sync_work",
    ExistingWorkPolicy.KEEP,   // don't enqueue if already pending
    syncWork
)

PeriodicWorkRequest

安排重复任务。最短间隔为 15 分钟:

val periodicSync = PeriodicWorkRequestBuilder<SyncWorker>(
    repeatInterval = 1, TimeUnit.HOURS
).build()

WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "hourly_sync",
    ExistingPeriodicWorkPolicy.KEEP,
    periodicSync
)

约束条件

仅在满足条件时运行任务,例如电量不低、已连接 WiFi 等:

val constraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.UNMETERED)  // WiFi only
    .setRequiresBatteryNotLow(true)
    .setRequiresCharging(false)
    .build()

val work = OneTimeWorkRequestBuilder<SyncWorker>()
    .setConstraints(constraints)
    .build()

WorkManager.getInstance(context).enqueue(work)

输入与输出数据

使用 Data 对象向 Worker 传入和传出数据:

// Enqueue with input data:
val inputData = workDataOf("user_id" to 42)
val work = OneTimeWorkRequestBuilder<SyncWorker>()
    .setInputData(inputData)
    .build()

// Inside the Worker:
class SyncWorker(...) : CoroutineWorker(...) {
    override suspend fun doWork(): Result {
        val userId = inputData.getInt("user_id", -1)

        // Pass output data back:
        val output = workDataOf("synced_count" to 10)
        return Result.success(output)
    }
}

观察任务状态

使用 getWorkInfoByIdLiveData 观察任务进度:

val workRequest = OneTimeWorkRequestBuilder<SyncWorker>().build()
WorkManager.getInstance(this).enqueue(workRequest)

WorkManager.getInstance(this)
    .getWorkInfoByIdLiveData(workRequest.id)
    .observe(this) { info ->
        when (info?.state) {
            WorkInfo.State.RUNNING   -> binding.tvStatus.text = "Syncing..."
            WorkInfo.State.SUCCEEDED -> binding.tvStatus.text = "Done!"
            WorkInfo.State.FAILED    -> binding.tvStatus.text = "Failed"
            else                     -> {}
        }
    }

链接任务

使用任务链按顺序或并行运行任务:

val downloadWork  = OneTimeWorkRequestBuilder<DownloadWorker>().build()
val processWork   = OneTimeWorkRequestBuilder<ProcessWorker>().build()
val uploadWork    = OneTimeWorkRequestBuilder<UploadWorker>().build()

// Sequential: download → process → upload
WorkManager.getInstance(context)
    .beginWith(downloadWork)
    .then(processWork)
    .then(uploadWork)
    .enqueue()

// Parallel then merge:
WorkManager.getInstance(context)
    .beginWith(listOf(downloadWork, processWork))  // both run in parallel
    .then(uploadWork)                              // runs after both finish
    .enqueue()

WorkManager 与替代方案

应该在什么时候使用哪种方案:

  • WorkManager — 可延迟、必须执行且基于约束条件的任务。最适合数据同步、上传和清理任务。
  • 协程 / ViewModel — 与应用保持打开状态相关的任务。应用被终止时会停止。
  • AlarmManager — 精确时间的提醒(例如日历提醒)。需要谨慎处理电量问题。
  • 前台服务 — 用户知情的长时间运行任务(例如音乐播放、导航)。

快速检查

PeriodicWorkRequest 的最短重复间隔是多少?

回顾:WorkManager

WorkManager 是处理必须执行的后台任务的合适工具:

  • 继承 CoroutineWorker 并实现 doWork()
  • 返回 Result.success()、.failure() 或 .retry()
  • 单次运行使用 OneTimeWorkRequest,重复运行使用 PeriodicWorkRequest
  • 使用 Constraints 添加 WiFi、低电量等条件
  • 使用 workDataOf() 传递数据
  • 使用 beginWith().then().enqueue() 链接任务

接下来:学习用于构建精美界面的 Material Design 组件。

常见问题解答

「WorkManager 与后台任务」课时是免费的吗?

是的 — 「WorkManager 与后台任务」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Android Academy 课程的其余内容,请升级到 CoddyKit PRO。 Android Academy 课程共包含 6 节课。

「WorkManager 与后台任务」这节课中我会学到什么?

使用 WorkManager 安排有保障的后台工作。使用 OneTimeWorkRequest、PeriodicWorkRequest、约束、数据传递和工作链。 你通过在浏览器中直接运行的动手代码来练习 Android Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Android Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Android Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 5 节课,共 6 节。

「WorkManager 与后台任务」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Android Academy 课中编写并运行代码吗?

能。每节 Android Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Retrofit 与 REST API
  2. 使用 Coil 加载图片
  3. 错误处理与用户体验
  4. 推送通知
  5. WorkManager 与后台任务
  6. 发布到 Play Store
← 返回 Android Academy