opoojkk

WorkManager是怎样工作的

lxx
目次

在 Android 开发中,WorkManager 是官方推荐的后台任务管理框架。它的特点是 任务可靠执行,即便应用退出或设备重启,也能保证任务最终执行。本文尝试从源码和运行机制角度梳理 WorkManager 的执行逻辑。


一个最简单的例子 #

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class UploadWorker(appContext: Context, workerParams: WorkerParameters) :
    Worker(appContext, workerParams) {
    override fun doWork(): Result {
        // 任务逻辑
        return Result.success()
    }
}

val uploadWorkRequest: WorkRequest =
    OneTimeWorkRequestBuilder<UploadWorker>().build()

WorkManager.getInstance(this).enqueue(uploadWorkRequest)

WorkManager 的关键点 #

  1. 基于队列思想:和常见任务队列类似,支持依赖、状态跟踪。
  2. 持久化任务信息:任务存储在数据库中,确保系统杀进程后还能恢复。
  3. 多种调度器实现:底层通过 JobSchedulerGCMAlarmManager 触发执行。

任务入队:数据库层面 #

数据库核心表:WorkSpec

WorkSpec:存储一个逻辑工作单元的全部信息(id、约束条件、状态等)。

入队时的逻辑:

  1. 依赖检查

    • 确保所有父任务已经入库(通过 id 判断)。
    • 根据任务名称和策略(APPENDKEEP 等)处理冲突。
  2. 常见策略

    • APPEND / APPEND_OR_REPLACE

      • 记录已有任务的依赖 id。
      • 如果依赖被取消或失败,删除相关任务。
    • KEEP

      • 已有任务状态为 ENQUEUEDRUNNING 时,忽略新任务。
      • 否则删除旧任务,重新入库。
  3. 插入新记录

    • 判断前置任务和执行状态,更新状态。
    • 插入数据库(WorkSpec、依赖表、标签表、名称表)。
    • 返回是否需要实际执行(state == ENQUEUED)。

任务执行过程 #

当任务需要执行时:

  1. 标记执行状态

    • 队列中触发条件(如 ContentUri)满足。
    • 状态非完成的任务被调度。
  2. 调度器决定执行方式 WorkManager 会在初始化时选择一个合适的 Scheduler

    • API 23+SystemJobScheduler (基于 JobScheduler)
    • 旧设备 → 优先用 GcmScheduler(若有 GCM),否则用 SystemAlarmScheduler (基于 AlarmManager)
  3. 执行逻辑

    • SystemJobScheduler

      1. 保存状态,将 WorkSpec 与系统 JobInfo 绑定。

      2. JobInfo 配置条件:

        • 充电 / 空闲 / 网络约束
        • API 29 前至少需要一个条件(默认延迟)
        • 前台任务标记
        • API 24+ 支持 ContentUri Trigger
        • API 26+ 支持低电量 / 低存储约束
      3. API 23 的特殊情况:只有当队列里有两个任务时才会触发 → 会补充一个任务保证执行。

    • SystemAlarmScheduler

      • 直接通过 startService() 粗暴触发。

Worker 的创建与绑定 #

执行时,WorkManager 根据数据库中的 WorkSpec 动态创建 Worker 实例

1
2
3
4
5
val worker = configuration.workerFactory.createWorkerWithDefaultFallback(
    appContext,
    workSpec.workerClassName,
    params
)

这里的关键点:


稳定执行的保障 #

WorkManager 的稳定性来源于以下几个方面:

  1. 持久化:所有任务与依赖存储在数据库中。
  2. 多重调度器适配:根据 API Level 和设备环境选择合适的调度方式。
  3. 状态机驱动:任务状态(ENQUEUEDRUNNINGFAILEDSUCCEEDED 等)严格受数据库驱动。
  4. WorkerFactory:确保任务实例可恢复,避免直接依赖内存对象。

总结 #

WorkManager 的核心是 数据库 + 调度器

因此,无论应用进程是否被杀、设备是否重启,任务都能在条件满足时重新调度并最终执行。这也是 WorkManager 相比于直接使用 JobSchedulerAlarmManager 的最大优势。


参考:

标签:
Categories: