Android Jetpack WorkManager 详解

Jetpack WorkManager 是 Android 推荐的后台任务调度库,用于处理延迟任务、周期性任务及需保证执行的任务(即使应用退出或设备重启)。本文会从核心概念、使用示例、适用场景、注意事项到版本兼容性进行全面解析。

一、核心概念

1. Worker

任务执行单元,需继承 CoroutineWorker(协程)或 Worker(同步),重写 doWork() 方法。

2. WorkRequest

定义任务的触发条件(如网络状态、充电状态)、约束、重试策略等,分两种类型:

  • OneTimeWorkRequest:一次性任务。
  • PeriodicWorkRequest:周期性任务(间隔 ≥15分钟)。

3. WorkManager

任务调度器,负责将 WorkRequest 加入队列并管理执行。

4. WorkInfo

任务状态(ENQUEUEDRUNNINGSUCCEEDEDFAILEDCANCELLED)。

二、使用示例

1. 基础配置

  • 添加依赖

    gradle 复制代码
    // build.gradle (app)
    dependencies {
        implementation "androidx.work:work-runtime-ktx:2.9.0"
        // 可选:测试支持
        androidTestImplementation "androidx.work:work-testing:2.9.0"
    }

2. 定义 Worker

kotlin 复制代码
class UploadWorker(
    context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        // 获取输入数据
        val data = inputData.getString("KEY_FILE_URI") ?: return Result.failure()

        return try {
            // 执行上传逻辑(模拟耗时)
            uploadFileToServer(data)
            Result.success(workDataOf("KEY_RESULT" to "Success"))
        } catch (e: Exception) {
            Result.retry() // 或 Result.failure()
        }
    }

    private suspend fun uploadFileToServer(uri: String) {
        delay(5000) // 模拟上传
    }
}

3. 创建 WorkRequest 并提交

kotlin 复制代码
// 定义约束:网络连接且设备充电时执行
val constraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresCharging(true)
    .build()

// 创建输入数据
val inputData = workDataOf("KEY_FILE_URI" to "content://file_path")

// 构建一次性请求
val uploadRequest = OneTimeWorkRequestBuilder<UploadWorker>()
    .setInputData(inputData)
    .setConstraints(constraints)
    .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS) // 重试策略
    .build()

// 提交任务
WorkManager.getInstance(context).enqueue(uploadRequest)

4. 观察任务状态

kotlin 复制代码
WorkManager.getInstance(context)
    .getWorkInfoByIdLiveData(uploadRequest.id)
    .observe(this) { workInfo ->
        when (workInfo?.state) {
            WorkInfo.State.SUCCEEDED -> {
                val result = workInfo.outputData.getString("KEY_RESULT")
                Toast.makeText(context, "上传成功:$result", Toast.LENGTH_SHORT).show()
            }
            WorkInfo.State.FAILED -> { /* 处理失败 */ }
            WorkInfo.State.CANCELLED -> { /* 处理取消 */ }
            else -> { /* 其他状态 */ }
        }
    }

5. 周期性任务

kotlin 复制代码
val dailyRequest = PeriodicWorkRequestBuilder<SyncWorker>(
    1, TimeUnit.DAYS, // 间隔周期
    15, TimeUnit.MINUTES // 灵活间隔(实际间隔为周期+灵活间隔)
).build()

WorkManager.getInstance(context).enqueue(dailyRequest)

三、适用场景

1. 需保证执行的任务

  • 日志上传、数据同步(即使应用关闭或设备重启)。

2. 延迟任务

  • 用户退出界面后提交反馈、缓存清理。

3. 条件触发任务

  • 仅在充电时备份数据、有网络时下载文件。

4. 任务链与依赖

  • 顺序执行:压缩文件 → 上传 → 发送通知。

    kotlin 复制代码
    WorkManager.getInstance(context)
        .beginWith(compressWorkRequest)
        .then(uploadWorkRequest)
        .then(notifyWorkRequest)
        .enqueue()

四、注意事项

1. 任务执行时间限制

  • 普通 Worker:默认约10分钟(Android 12+ 限制为10分钟)。
  • 长时任务 :使用 ForegroundService 替代。

2. 避免任务冲突

  • 使用 UniqueWorkPolicyREPLACEKEEPAPPEND)管理唯一任务。

3. 输入输出数据限制

  • 数据大小不超过 10KB (使用 Data 类序列化)。

4. 测试与调试

  • 使用 WorkManagerTestInitHelper 模拟任务执行。

    kotlin 复制代码
    @RunWith(AndroidJUnit4::class)
    class UploadWorkerTest {
        @Test
        fun testUploadWorker() = runTest {
            val request = OneTimeWorkRequestBuilder<UploadWorker>().build()
            val testDriver = WorkManagerTestInitHelper.getTestDriver(context)
            WorkManager.getInstance(context).enqueue(request).result.get()
            testDriver?.setAllConstraintsMet(request.id) // 触发约束条件
            val workInfo = WorkManager.getInstance(context).getWorkInfoById(request.id).get()
            assertThat(workInfo.state).isEqualTo(WorkInfo.State.SUCCEEDED)
        }
    }

五、版本兼容性

Android 版本 WorkManager 行为
API ≥ 23 (Android 6.0+) 使用 JobScheduler(系统级调度,低功耗)。
API 21-22 使用 JobSchedulerAlarmManager 组合。
API ≤ 20 使用 AlarmManagerBroadcastReceiver
所有版本 任务持久化存储(设备重启后自动重新调度)。
  • 最低支持:API 14(Android 4.0)。

  • ProGuard 规则 :保留 Worker 类。

    proguard 复制代码
    -keep class * extends androidx.work.Worker
    -keep class * extends androidx.work.CoroutineWorker

六、与 Hilt 集成(依赖注入)

一文带你了解 Android 中 Dagger/Hilt 的原理和简单使用

kotlin 复制代码
@HiltWorker
class AnalyticsWorker @AssistedInject constructor(
    @Assisted context: Context,
    @Assisted params: WorkerParameters,
    private val analyticsService: AnalyticsService // 注入依赖
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        analyticsService.logEvent("worker_started")
        return Result.success()
    }
}

七、总结

  • 优势:统一后台任务调度、支持复杂约束、自动兼容不同 API 版本。
  • 推荐场景:数据同步、日志上传、条件触发的后台任务。
  • 最佳实践
    • 短时任务使用 CoroutineWorker
    • 长时任务改用前台服务。
    • 合理设置 ConstraintsBackoffCriteria
    • 使用 WorkManagerTestInitHelper 进行单元测试。

通过 WorkManager,开发者可高效管理后台任务,确保用户体验与设备性能的平衡。

更多分享

  1. 一文吃透Kotlin中冷流(Clod Flow)和热流(Hot Flow)
  2. 一文带你吃透Kotlin协程的launch()和async()的区别
  3. Kotlin 作用域函数(let、run、with、apply、also)的使用指南
  4. Android 详解:高频使用的 8 种设计模式的核心思想和代码实现
  5. 一文带你吃透Kotlin中 lateinit 和 by lazy 的区别和用法
  6. Android ContentProvider 详解及结合 Jetpack Startup 的优化实践
相关推荐
zhangphil21 分钟前
Android Coil 3拦截器Interceptor计算单次请求耗时,Kotlin
android·kotlin
DokiDoki之父1 小时前
多线程—飞机大战排行榜功能(2.0版本)
android·java·开发语言
用户2018792831673 小时前
强制关闭生命周期延时的Activity实现思路
android
用户2018792831673 小时前
Activity后生命周期暂停问题
android
用户2018792831673 小时前
浅析:WindowManager添加的 View 的事件传递机制
android
顾林海3 小时前
从"面条代码"到"精装别墅":Android MVPS架构的逆袭之路
android·面试·架构
wayne2143 小时前
Kotlin 空安全完整指南:彻底告别NullPointerException
kotlin
白夜4 小时前
Android 开发工程常识
android
编程乐学4 小时前
原创模板--基于 Android 开发的驾考训练App
android·android studio·大作业·移动端开发·安卓移动开发·驾考宝典·驾考app