WorkManager 笔记

4 阅读2分钟

🧩 WorkManager:兼容性优先的现代化方案

WorkManager是Jetpack组件,它在底层会自动选择最佳后端(包括JobScheduler),能兼容至API 14,并支持更灵活的任务链和约束。

使用步骤与示例:

  1. 添加依赖app/build.gradle文件中添加:

    dependencies {
        def work_version = "2.8.0" // 使用当时最新稳定版本
        implementation "androidx.work:work-runtime-ktx:$work_version"
    }
    
  2. 定义一个Worker Worker是执行任务的单元。

    // 1. 定义你的Worker(例如一个图片压缩任务)
    class CompressImageWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
        override fun doWork(): Result {
            // 这个方法在后台线程执行,无需担心主线程阻塞
            val imagePath = inputData.getString("IMAGE_PATH")
    
            return try {
                // 执行实际的压缩工作...
                Log.d("WorkManager", "开始压缩图片: $imagePath")
                // 模拟耗时操作
                Thread.sleep(2000)
                
                // 输出结果
                val outputData = workDataOf("COMPRESSED_PATH" to "/sdcard/compressed.jpg")
                Result.success(outputData) // 任务成功完成
                // 也可返回 Result.failure() 或 Result.retry()
            } catch (e: Exception) {
                Log.e("WorkManager", "压缩失败", e)
                Result.failure()
            }
        }
    }
    
  3. 配置WorkRequest并调度任务 你可以创建一次性或周期性的请求。

    // 2. 配置并调度一个一次性任务
    fun scheduleOneTimeCompression(context: Context, imagePath: String) {
        // 创建输入数据
        val inputData = workDataOf("IMAGE_PATH" to imagePath)
    
        // 设置约束条件
        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED) // 需要网络
            .setRequiresCharging(false)                    // 不需要充电
            .setRequiresBatteryNotLow(true)                // 电池不能处于低电量模式
            .build()
    
        // 构建一次性工作请求
        val compressionWork = OneTimeWorkRequestBuilder<CompressImageWorker>()
            .setInputData(inputData)
            .setConstraints(constraints)
            .setInitialDelay(10, TimeUnit.SECONDS) // 延迟10秒执行
            .addTag("image_processing")            // 给任务打标签,便于后续查询或取消
            .build()
    
        // 提交给系统调度
        WorkManager.getInstance(context).enqueue(compressionWork)
    }
    
    // 3. 调度一个周期性任务(例如每隔24小时备份一次)
    fun schedulePeriodicBackup(context: Context) {
        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.UNMETERED) // 仅在Wi-Fi下
            .setRequiresCharging(true)                     // 仅在充电时
            .build()
    
        val periodicBackupWork = PeriodicWorkRequestBuilder<BackupWorker>(
            24, TimeUnit.HOURS, // 重复间隔
            15, TimeUnit.MINUTES // 柔性间隔:允许在执行窗口内有最多15分钟的延迟,增加批量执行机会以省电
        ).setConstraints(constraints)
         .build()
    
        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "unique_backup_work", // 唯一名称,确保同一时间只有一个此类任务
            ExistingPeriodicWorkPolicy.KEEP, // 如果已存在同名任务,保留旧的,不调度新的
            periodicBackupWork
        )
    }
    

WorkManager高级特性:

  • 任务链:可以按顺序或并行执行多个任务。
    WorkManager.getInstance(context)
        .beginWith(listOf(workA, workB)) // 先并行执行A和B
        .then(workC)                     // 然后执行C
        .then(workD)                     // 再执行D
        .enqueue()
    
  • 观察任务状态
    WorkManager.getInstance(context).getWorkInfoByIdLiveData(compressionWork.id)
        .observe(this) { workInfo ->
            if (workInfo?.state == WorkInfo.State.SUCCEEDED) {
                val resultPath = workInfo.outputData.getString("COMPRESSED_PATH")
                // 更新UI...
            }
        }
    

💎 选择建议总结

特性JobSchedulerWorkManager
最低APIAPI 21 (Android 5.0)API 14 (Android 4.0)
设计目标系统级精准调度,电池优化兼容性优先,使用简单,功能丰富
任务链不支持支持(顺序/并行)
约束条件基础约束(网络、充电)更丰富(电池是否充足、存储空间等)
任务持久化需要setPersisted和权限自动处理
推荐使用场景面向Android 5.0+,需要精确控制的系统级任务绝大多数情况,尤其是需要兼容旧版本或使用复杂任务链

总的来说,对于现代应用开发,WorkManager通常是首选,除非你的应用有非常特殊的、仅针对新系统的精确调度需求。