目录
  1. 1. 一、核心概念
  2. 2. 二、任务约束与链式调度
  3. 3. 三、底层调度机制
  4. 4. 四、任务观察
  5. 5. 面试常考问题
JetPack全家桶(七)之WorkManager任务调度

WorkManager 是 Jetpack 中用于处理可延迟但必须执行的后台任务的调度库。它能保证任务在所有场景下被执行——即使应用退出、设备重启。WorkManager 内部根据 API 级别智能选择底层调度器。

一、核心概念

Worker:实际执行任务的单元,继承它并实现 doWork() 方法。

class UploadLogWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {

override suspend fun doWork(): Result {
val logPath = inputData.getString("log_path") ?: return Result.failure()
return try {
uploadLog(logPath)
Result.success(
workDataOf("uploaded_size" to 102400L)
)
} catch (e: Exception) {
if (runAttemptCount < 3) Result.retry()
else Result.failure(workDataOf("error" to e.message))
}
}
}

WorkRequest:描述”执行什么 Worker、何时执行、有哪些约束”。分为两种:

  • OneTimeWorkRequest:一次性任务
  • PeriodicWorkRequest:周期任务,最小间隔 15 分钟

二、任务约束与链式调度

// 约束条件:网络连接 + 电量充足 + 设备空闲
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.setRequiresDeviceIdle(true)
.build()

val compressWork = OneTimeWorkRequestBuilder<CompressWorker>()
.setConstraints(constraints)
.setInputData(workDataOf("file_uri" to uri.toString()))
.build()

val uploadWork = OneTimeWorkRequestBuilder<UploadLogWorker>()
.setConstraints(constraints)
.build()

// 链式调度:先压缩,再上传
WorkManager.getInstance(context)
.beginWith(compressWork)
.then(uploadWork)
.enqueue()

数据在 Worker 间通过 Data 对象传递(底层是 Map<String, Any>),每个 Worker 通过 inputData 读取输入,通过 Result.success(workDataOf(...)) 输出数据给下游 Worker。

三、底层调度机制

WorkManager 内部根据 API 级别自动选择:

API 范围 底层调度器
API 23+ JobScheduler
API 14-22 BroadcastReceiver + AlarmManager

WorkManager 还将任务状态持久化到 Room 数据库(WorkSpec 表),确保进程被杀或设备重启后任务不丢失。

四、任务观察

WorkManager.getInstance(context)
.getWorkInfoByIdLiveData(uploadWork.id)
.observe(lifecycleOwner) { workInfo ->
when (workInfo.state) {
WorkInfo.State.ENQUEUED -> showPending()
WorkInfo.State.RUNNING -> showProgress()
WorkInfo.State.SUCCEEDED -> {
val size = workInfo.outputData.getLong("uploaded_size", 0)
showSuccess(size)
}
WorkInfo.State.FAILED -> showError(workInfo.outputData.getString("error"))
else -> {}
}
}

面试常考问题

Q1:WorkManager 与 Service、JobScheduler、AlarmManager 的区别?

WorkManager 是最上层封装,内部根据 API 自动路由到 JobScheduler(23+)或 AlarmManager(14-22),同时提供约束、链式调度、状态观察等高级功能。Service 适合前台任务,AlarmManager 适合精确定时,JobScheduler 适合条件触发的后台任务但仅限 API 21+。

Q2:doWork() 在哪个线程执行?

Worker 的 doWork() 默认在后台线程执行(通过内部 Executor 线程池)。CoroutineWorker 的 doWork()Dispatchers.Default 上运行。切勿在 Worker 中直接操作 UI。

Q3:PeriodicWorkRequest 最小间隔为何是 15 分钟?

为了减少后台唤醒对电池的消耗,Android 系统强制 PeriodicWorkRequest 的最小周期为 15 分钟(MIN_PERIODIC_INTERVAL_MILLIS)。如需更短间隔,应使用前台 Service 或 AlarmManager。源码:androidx.work.impl.model.WorkSpec.MIN_PERIODIC_INTERVAL_MILLIS

打赏
  • 微信
  • 支付宝

评论