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 的优化实践
相关推荐
alexhilton17 分钟前
实战:在Compose中优雅地实现提示
android·kotlin·android jetpack
每次的天空2 小时前
Android面试总结之Android RecyclerView:从基础机制到缓存优化
android
该怎么办呢3 小时前
原生android实现定位java实现
android·java·gitee
Android小码家4 小时前
Live555+Windows+MSys2 编译Androidso库和运行使用(三,实战篇)
android·live555
Tsing7224 小时前
Android vulkan示例
android
每次的天空5 小时前
高性能 Android 自定义 View:数据渲染与事件分发的双重优化
android
KdanMin5 小时前
Android 13组合键截屏功能的彻底移除实战
android
_祝你今天愉快5 小时前
安卓源码学习之【导航方式切换分析及实战】
android·源码
&有梦想的咸鱼&5 小时前
Android Compose 框架物理动画之弹簧动画(Spring、SpringSpec)深入剖析(二十七)
android·java·spring
Wgllss5 小时前
Android Compose轻松绘制地图可视化图表,带点击事件,可扩展二次开发
android·架构·android jetpack