1. 持久化任务恢复场景分析

当应用在后台执行上传、数据库同步、日志压缩等耗时任务时,系统可能因内存不足杀进程,或用户主动重启设备。如果任务状态只保存在内存中,恢复后无从得知进度,可能导致数据重复或丢失。Room + WorkManager 的组合提供了持久化任务恢复的标准化方案:Room 存储任务元数据与进度,WorkManager 读取 Room 并重新调度未完成的工作。

1.1 关键中断场景对比

下表对比了四种典型场景下 WorkManager 与 Room 的协作行为:

场景WorkManager 行为Room 数据状态恢复能力
正常执行Worker 按约束运行,完成后标记 SUCCESS任务状态更新为 COMPLETED无恢复需要
应用重启WorkManager 初始化后查询未完成的 WorkSpecRoom 中保留中间状态(如 PROGRESS=50%)自动恢复,Worker 从断点继续
进程被杀系统重启延迟恢复,WorkManager 在下次启动时重新调度Room 任务记录完整,不存在脏数据无需人工干预,数据不丢失
任务状态丢失WorkManager 无法得知之前进度,需依赖 Room 存储的自定义状态字段若未持久化自定义字段,任务还原到起始点需额外校验,建议存储幂等
设计要点:始终在 Worker 中通过 Room 更新任务状态,而非仅依赖 WorkManager 内置的 Result。因为 WorkManager 的 WorkSpec 在进程被杀后可能丢失自定义数据。

1.2 Room 数据库:任务的持久化锚点

Room 负责存储任务的元数据(ID、类型、进度、重试次数)和执行过程中产生的临时结果。一个典型的任务实体定义如下:

@Entity(tableName = "pending_tasks")
data class PendingTask(
    @PrimaryKey val taskId: String,
    val type: String,               // "upload", "sync", "compress"
    val progress: Int = 0,          // 0-100
    val status: String = "PENDING", // PENDING, RUNNING, COMPLETED, FAILED
    val retryCount: Int = 0,
    val nextRetryTime: Long? = null
)

通过 DAO 增删改查,Worker 可以在任何阶段持久化当前进度。即使进程被完全杀死,Room 文件仍在内部存储中,重启后即可读取。

1.3 WorkManager 调度与恢复流程

WorkManager 内部维护一个 SQLite 数据库(WorkDatabase),记录所有 WorkSpec 和 WorkProgress。当进程被杀重启时,WorkManager 会:

  1. 初始化时扫描 WorkDatabase 中状态为 ENQUEUED 或 RUNNING 的 WorkSpec;
  2. 根据约束(网络、充电等)重新将 Worker 加入调度队列;
  3. 在 Worker 的 doWork() 中,主动查询 Room 中的 PendingTask 表,读取之前保存的进度和参数,继续执行。

关键代码片段——WorkManager 初始化与恢复触发:

// Application 初始化
WorkManager.initialize(this, Configuration.Builder()
    .setMinimumLoggingLevel(android.util.Log.INFO)
    .build())

// 恢复逻辑通常在 App Startup 或首次打开 Activity 时
val workManager = WorkManager.getInstance(application)
workManager.getWorkInfosByTagLiveData("restore_tasks")
    .observe(owner) { workInfos ->
        // 检查是否有未完成的 Worker,若有则同步 Room 中的任务
        if (workInfos.any { it.state == WorkInfo.State.ENQUEUED }) {
            restoreFromRoom()
        }
    }

1.4 完整恢复流程

下图展示了从任务创建到进程被杀再到恢复执行的完整数据流:

持久化任务恢复流程 任务持久化恢复流程 任务创建 Room 持久化存储 WorkManager 调度 进程被杀 / 重启 恢复执行 持久化 调度 读取 异常 重启识别 说明 Worker 重启后通过 Room 读取上次保存的进度(如已处理 30 个文件), 从第 31 个文件继续执行,避免重复工作。Room 中须标记幂等 。
注意:进程被杀后,doWork() 中正在运行的代码会被中断,再次执行时会重新进入该方法。务必在 onStopped() 或 Result.retry() 回调中保存现场到 Room,否则恢复后只能从头开始。

通过上述分析可以看出,Room 提供了任务状态的可靠存储层,WorkManager 保证了调度生命周期的系统级恢复能力。二者结合,能够覆盖绝大多数业务场景下的任务持久化要求。