Android WorkManager 指南 — 后台任务调度

码匠2个月前大语言模型6220

WorkManager 能够在不同的 Android 版本中可靠地处理后台任务,同时尊重 Doze 模式和电池优化。

CoroutineWorker 基础

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

    override suspend fun doWork(): Result {
        return try {
            val result = performBackgroundTask()
            Result.success()
        } catch (e: Exception) {
            when {
                e is IOException -> Result.retry()
                else -> Result.failure()
            }
        }
    }

    private suspend fun performBackgroundTask(): String {
        delay(2000)
        return "Task completed"
    }
}

带约束条件的 WorkRequest

一次性工作请求:

val constraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresBatteryNotLow(true)
    .setRequiresDeviceIdle(false)
    .build()

val workRequest = OneTimeWorkRequestBuilder<MyCoroutineWorker>()
    .setConstraints(constraints)
    .setBackoffCriteria(
        backoffPolicy = BackoffPolicy.EXPONENTIAL,
        initialDelay = 15,
        timeUnit = TimeUnit.MINUTES
    )
    .build()

WorkManager.getInstance(context).enqueueUniqueWork(
    "sync_work",
    ExistingWorkPolicy.KEEP,
    workRequest
)

周期性工作请求

val periodicWorkRequest = PeriodicWorkRequestBuilder<MyCoroutineWorker>(
    15, TimeUnit.MINUTES
).setConstraints(constraints).build()

WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "periodic_sync",
    ExistingPeriodicWorkPolicy.KEEP,
    periodicWorkRequest
)

输入/输出数据

val inputData = workDataOf(
    "user_id" to 123,
    "action" to "sync"
)

val workRequest = OneTimeWorkRequestBuilder<MyCoroutineWorker>()
    .setInputData(inputData)
    .build()

// 在 Worker 中
override suspend fun doWork(): Result {
    val userId = inputData.getInt("user_id", -1)
    val action = inputData.getString("action")

    val outputData = workDataOf(
        "result" to "success",
        "timestamp" to System.currentTimeMillis()
    )

    return Result.success(outputData)
}

WorkRequest 链式调用

顺序执行:

val uploadRequest = OneTimeWorkRequestBuilder<UploadWorker>().build()
val syncRequest = OneTimeWorkRequestBuilder<SyncWorker>().build()
val notifyRequest = OneTimeWorkRequestBuilder<NotifyWorker>().build()

WorkManager.getInstance(context)
    .beginWith(uploadRequest)
    .then(syncRequest)
    .then(notifyRequest)
    .enqueue()

并行 + 顺序执行:

val task1 = OneTimeWorkRequestBuilder<Task1Worker>().build()
val task2 = OneTimeWorkRequestBuilder<Task2Worker>().build()
val merge = OneTimeWorkRequestBuilder<MergeWorker>().build()

WorkManager.getInstance(context)
    .beginWith(listOf(task1, task2)) // 并行运行
    .then(merge) // 然后合并结果
    .enqueue()

在 Compose 中监控进度

@Composable
fun WorkProgressScreen() {
    val workManager = WorkManager.getInstance(LocalContext.current)
    val workState by workManager
        .getWorkInfoByIdLiveData(workId)
        .observeAsState()

    Column(Modifier.fillMaxSize()) {
        when {
            workState?.state == WorkInfo.State.RUNNING -> {
                val progress = workState?.progress?.getInt("progress", 0) ?: 0
                LinearProgressIndicator(progress = progress / 100f)
                Text("Progress: $progress%")
            }
            workState?.state == WorkInfo.State.SUCCEEDED -> {
                Text("Task completed successfully")
            }
            workState?.state == WorkInfo.State.FAILED -> {
                Text("Task failed")
            }
        }
    }
}

关键要点

  • 使用 CoroutineWorker 处理挂起操作

  • 设置约束条件以获得最佳执行条件

  • 使用 beginWith/then 链式调用处理复杂工作流

  • 通过 workDataOf 传递数据(JSON 可序列化类型)

  • 在 UI 中使用 observeAsState 和 Compose 监控状态

  • 为网络重试实现指数退避策略

相关文章

价值十亿美元的三个词:向确定性漂移(DriDe)

价值十亿美元的三个词:向确定性漂移(DriDe) 我怀疑我不是第一个想到这个概念的人,但我可能是第一个给它命名的人。 向确定性漂移(DriDe - 读作"DRY'd",即"Don't Repeat...

你的 AI 代码审查员没有人可以反驳

你的 AI 代码审查员没有人可以反驳 让 AI 审查你的代码,你得到的只是一个模型的观点。一次对差异的检查。无论它首先关注什么。 有时这样就可以了。有时它确实能发现问题。 但如果你曾经在一个有强...

Ollama模型删除教程:命令行与API两种方法详解

Ollama模型删除教程:命令行与API两种方法详解

在使用Ollama进行本地大模型部署与管理时,随着模型的不断更新和需求的变化,删除不再需要的模型以释放存储空间是常见操作。本文将详细介绍两种在Ollama中删除模型的方法,帮助你高效管理本地模型资源。...

为什么选择本地大语言模型而非纯云端方案

将 MFS Corp 构建为一个自主的 AI 驱动组织意味着我们需要在早期就做出艰难的基础设施选择。其中最大的一个?本地大语言模型 vs 云端 API。剧透:我们两者都选择了。原因如下。选择本地的理由...

OpenClaw 对接大语言模型 API 全配置指南

OpenClaw 作为开源 AI 智能体网关,核心能力是通过统一接口对接各类大语言模型 API,实现多模型灵活切换与统一调用。其配置核心围绕 baseUrl(API 基础地址)、apiKey(API...

OpenClaw 阿里云百炼配置

阿里云百炼作为阿里云推出的大模型服务平台,为开发者提供了强大的 AI 能力。通过 OpenClaw 集成阿里云百炼,可以实现智能对话、内容生成、代码辅助等丰富功能。 环境准备 1. 获取阿里云百炼...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。