以下是 androidx.work:work-runtime-ktx 的常见用法示例,结合 Kotlin 特性展示如何简化后台任务开发:

WorkManager常见的使用说明 在包androidx.work:work-runtime-ktx_数据_02

一、一次性任务(最简单场景)

场景:

点击按钮后,调度一个后台任务(如打印日志或网络请求),任务无需重复执行。

代码实现:
  1. 定义 Worker(使用 CoroutineWorker 简化协程处理)
    kotlin
class SimpleWorker(
    context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result {
        // 模拟耗时操作(如延迟 2 秒)
        delay(2000)
        Log.d("WorkManager", "SimpleWorker 执行完成")
        return Result.success() // 任务成功
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  1. 调度任务(在 Activity/Fragment 中)
    kotlin
// 构建任务(使用 KTX 链式配置)
val workRequest = OneTimeWorkRequestBuilder<SimpleWorker>()
    .setInitialDelay(1, TimeUnit.SECONDS) // 延迟 1 秒执行
    .build()

// 提交任务(KTX 扩展函数 `enqueue`)
WorkManager.getInstance(this).enqueue(workRequest)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

二、周期性任务(定时执行)

场景:

每天早上 9 点执行数据同步任务,使用唯一任务名避免重复调度。

代码实现:

kotlin

// 定义周期性 Worker
class DailySyncWorker(
    context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result {
        // 执行数据同步逻辑
        Log.d("WorkManager", "每日数据同步完成")
        return Result.success()
    }
}

// 调度任务(在 Application 或初始化位置)
val dailyRequest = DailyWorkRequestBuilder<DailySyncWorker>()
    .setInitialDelay(9, TimeUnit.HOURS) // 首次执行时间:当前时间 + 9 小时
    .setConstraints(
        Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED) // 要求网络连接
            .build()
    )
    .build()

// 使用唯一任务名确保唯一性(避免重复创建)
WorkManager.getInstance(this).enqueueUniqueRepeatableWork(
    "daily_sync_work", // 唯一任务名
    ExistingWorkPolicy.REPLACE, // 若存在旧任务,替换为新任务
    dailyRequest
)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.

三、组合任务(顺序 / 并行执行)

场景:
  • 顺序任务:先下载文件(任务 A),再解析文件(任务 B)。
  • 并行任务:同时加载图片和数据,全部完成后更新界面。
代码实现:
  1. 顺序任务(Sequence)
    kotlin
// 定义任务 A(下载文件)
class DownloadWorker : CoroutineWorker { /* ... */ }
// 定义任务 B(解析文件)
class ParseWorker : CoroutineWorker { /* ... */ }

// 构建任务链
val downloadRequest = OneTimeWorkRequestBuilder<DownloadWorker>().build()
val parseRequest = OneTimeWorkRequestBuilder<ParseWorker>().build()

// 使用 KTX 的 beginSequence 按顺序执行
WorkManager.getInstance(this).beginSequence(
    listOf(downloadRequest, parseRequest)
).enqueue()

// 监听任务链状态(可选)
WorkManager.getInstance(this)
    .getWorkInfosByTagLiveData("sequence_tag") // 给任务添加标签
    .observe(this) { workInfos ->
        if (workInfos.all { it.state == WorkInfo.State.SUCCEEDED }) {
            Log.d("WorkManager", "顺序任务全部完成")
        }
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  1. 并行任务(Parallel)

kotlin

// 定义任务 X(加载图片)和任务 Y(加载数据)
class LoadImageWorker : CoroutineWorker { /* ... */ }
class LoadDataWorker : CoroutineWorker { /* ... */ }

// 并行执行两个任务
WorkManager.getInstance(this).beginParallel(
    listOf(
        OneTimeWorkRequestBuilder<LoadImageWorker>().build(),
        OneTimeWorkRequestBuilder<LoadDataWorker>().build()
    )
).enqueue()

// 监听并行任务完成(所有任务成功后触发)
WorkManager.getInstance(this)
    .getWorkInfosByTagLiveData("parallel_tag")
    .observe(this) { workInfos ->
        if (workInfos.all { it.state == WorkInfo.State.SUCCEEDED }) {
            updateUI() // 更新界面
        }
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

四、带输入输出数据的任务

场景:

Worker 接收参数(如文件路径),处理后返回结果(如处理状态)。

代码实现:
  1. 定义 Worker(接收输入,返回输出)
    kotlin
class ProcessFileWorker(
    context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result {
        // 获取输入数据
        val filePath = inputData.getString("file_path") ?: return Result.failure()

        // 模拟文件处理
        Log.d("WorkManager", "处理文件:$filePath")

        // 返回输出数据
        val outputData = workDataOf("status" to "success", "size" to 1024)
        return Result.success(outputData)
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  1. 调度任务并传递输入数据
    kotlin
val inputData = workDataOf("file_path" to "/data/file.txt")

val workRequest = OneTimeWorkRequestBuilder<ProcessFileWorker>()
    .setInputData(inputData) // 设置输入参数
    .build()

WorkManager.getInstance(this).enqueue(workRequest)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  1. 获取任务输出结果(通过 LiveData)

kotlin

val workId = workRequest.id // 保存任务 ID

WorkManager.getInstance(this)
    .getWorkInfoByIdLiveData(workId)
    .observe(this) { workInfo ->
        if (workInfo.state == WorkInfo.State.SUCCEEDED) {
            val status = workInfo.outputData.getString("status")
            Log.d("WorkManager", "任务结果:$status")
        }
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

五、使用协程简化任务调度

场景:

在协程中等待任务完成,避免回调嵌套(适用于需要同步获取任务结果的场景)。

代码实现:

kotlin

// 在协程作用域中执行
launch(Dispatchers.IO) {
    // 构建任务
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>().build()

    // 使用 KTX 的 runWorkRequest 提交任务并等待结果
    val result = WorkManager.getInstance(context).runWorkRequest(workRequest)

    // 处理结果
    if (result == WorkManager.Result.success()) {
        withContext(Dispatchers.Main) {
            Toast.makeText(context, "任务成功", Toast.LENGTH_SHORT).show()
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

六、任务约束(设备状态控制)

场景:

仅在设备充电且有 Wi-Fi 时执行大文件上传任务,避免消耗移动流量和电池。

代码实现:

kotlin

val constraints = Constraints.Builder()
    .setRequiresCharging(true) // 要求设备充电
    .setRequiredNetworkType(NetworkType.UNMETERED) // 要求非计量网络(如 Wi-Fi)
    .setRequiresDeviceIdle(false) // 不要求设备空闲(可立即执行,若条件满足)
    .build()

val uploadRequest = OneTimeWorkRequestBuilder<UploadWorker>()
    .setConstraints(constraints) // 应用约束
    .setBackoffCriteria( // 设置失败重试策略
        BackoffPolicy.EXPONENTIAL,
        initialDelay = 10,
        TimeUnit.SECONDS
    )
    .build()

WorkManager.getInstance(this).enqueue(uploadRequest)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

七、重复任务的唯一性管理

场景:

确保同一周期性任务仅存在一个实例(如每日报表任务),避免重复调度。

代码实现:

kotlin

// 定义唯一任务名
const val UNIQUE_WORK_NAME = "daily_report_work"

// 调度任务时检查唯一性
WorkManager.getInstance(this).enqueueUniqueRepeatableWork(
    UNIQUE_WORK_NAME,
    ExistingWorkPolicy.KEEP, // 若存在旧任务,保留并忽略新任务
    DailyWorkRequestBuilder<ReportWorker>()
        .setInitialDelay(9, TimeUnit.HOURS)
        .build()
)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

关键注意事项:

  1. Worker 线程安全CoroutineWorker 自动在后台线程执行 doWork,无需手动切换线程。
  2. 数据大小限制:输入输出数据建议使用轻量级数据(如 JSON 字符串),避免大数据量(如文件路径代替文件内容)。
  3. 任务测试:开发阶段可通过 WorkManager.getInstance(context).cancelAllWork() 清除测试任务,避免干扰。

通过以上示例,可以快速掌握 work-runtime-ktx 的核心用法,结合 Kotlin 协程和 DSL 特性提升开发效率。

更多细节可参考  WorkManager 中文官方文档