以下是 androidx.work:work-runtime-ktx
的常见用法示例,结合 Kotlin 特性展示如何简化后台任务开发:
一、一次性任务(最简单场景)
场景:
点击按钮后,调度一个后台任务(如打印日志或网络请求),任务无需重复执行。
代码实现:
- 定义 Worker(使用
CoroutineWorker
简化协程处理):
kotlin
- 调度任务(在 Activity/Fragment 中):
kotlin
二、周期性任务(定时执行)
场景:
每天早上 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)。
- 并行任务:同时加载图片和数据,全部完成后更新界面。
代码实现:
- 顺序任务(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.
- 并行任务(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 接收参数(如文件路径),处理后返回结果(如处理状态)。
代码实现:
- 定义 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.
- 调度任务并传递输入数据:
kotlin
- 获取任务输出结果(通过 LiveData):
kotlin
五、使用协程简化任务调度
场景:
在协程中等待任务完成,避免回调嵌套(适用于需要同步获取任务结果的场景)。
代码实现:
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.
关键注意事项:
- Worker 线程安全:
CoroutineWorker
自动在后台线程执行doWork
,无需手动切换线程。 - 数据大小限制:输入输出数据建议使用轻量级数据(如 JSON 字符串),避免大数据量(如文件路径代替文件内容)。
- 任务测试:开发阶段可通过
WorkManager.getInstance(context).cancelAllWork()
清除测试任务,避免干扰。
通过以上示例,可以快速掌握 work-runtime-ktx
的核心用法,结合 Kotlin 协程和 DSL 特性提升开发效率。
更多细节可参考 WorkManager 中文官方文档。