第一个Work任务:从零开始跑通你的后台任务

说实话,很多初学者第一次接触 WorkManager 时,都会被它那一堆概念搞懵。什么 Worker、WorkRequest、WorkManager 实例…… 我当年刚学的时候也这样。但你别怕,今天我们就亲手写一个最简单的任务,把它跑起来。

你想想看,再复杂的架构,本质上就是四个步骤:写代码 → 描述任务 → 提交 → 看结果。WorkManager 也不例外。

核心四步走:

  1. 创建一个 Worker 类,继承自 Worker
  2. 在 doWork() 里写你要执行的逻辑
  3. 构建一个 WorkRequest 来描述这个任务
  4. 通过 WorkManager 把任务加入队列

最后,别忘了观察一下任务到底执行了没有。

1. 创建 Worker 类 —— 任务的执行者

Worker 类说白了就是你的「任务本体」。所有你要在后台做的事情,都写在 doWork() 方法里。

我个人习惯把 Worker 类单独放在一个包下,比如 worker 包。这样项目结构清晰,找起来也方便。

class SimpleWorker(
    context: Context,
    params: WorkerParameters
) : Worker(context, params) {

    override fun doWork(): Result {
        // 这里写你的后台逻辑
        Log.d("SimpleWorker", "任务开始执行了")

        // 模拟耗时操作
        Thread.sleep(2000)

        Log.d("SimpleWorker", "任务执行完毕")

        // 返回成功
        return Result.success()
    }
}

嗯,这里要注意一点:doWork() 是在 WorkManager 的后台线程上执行的。所以你可以在里面放心做耗时操作,比如网络请求、数据库读写。但千万别在这里更新 UI,会崩溃的。

小提示:doWork() 方法必须返回一个 Result 对象。有三种选择:

  • Result.success() —— 任务成功
  • Result.failure() —— 任务失败
  • Result.retry() —— 需要重试

我曾经在项目里忘记返回 Result,编译直接报错。嗯,这个坑我替你们踩过了。

2. 构建 WorkRequest —— 任务的说明书

Worker 类写好了,但 WorkManager 还不知道怎么执行它。你需要一份「说明书」,告诉系统:这个任务什么时候跑、有什么约束、需不需要重试。

这份说明书就是 WorkRequest。最常用的是 OneTimeWorkRequest,顾名思义,只执行一次。

val workRequest: WorkRequest = OneTimeWorkRequestBuilder<SimpleWorker>()
    .setConstraints(Constraints.NONE)  // 无约束,立即执行
    .build()

你看,代码很简单。但我在实际项目中见过有人把 Constraints 写得很复杂,结果任务一直不触发。其实刚开始,你就用 Constraints.NONE 就好,跑通了再慢慢加条件。

3. 将任务加入队列 —— 交给系统去调度

现在任务和说明书都有了,就差最后一步:提交给 WorkManager。

val workManager = WorkManager.getInstance(context)
workManager.enqueue(workRequest)

就这么两行。调用 enqueue() 之后,WorkManager 会根据你设置的约束和策略,在合适的时机执行任务。

注意:WorkManager 是一个单例,不要重复创建实例。直接用 WorkManager.getInstance() 就好。我见过有人每次调用都 new 一个,结果任务状态全乱了。

4. 观察任务执行状态 —— 看看它到底跑没跑

任务提交了,怎么知道它执行了没有?WorkManager 提供了 LiveDataStateFlow 来观察任务状态。

workManager.getWorkInfoByIdLiveData(workRequest.id)
    .observe(this, Observer { workInfo ->
        if (workInfo != null) {
            when (workInfo.state) {
                WorkInfo.State.ENQUEUED -> Log.d("WorkStatus", "任务已加入队列")
                WorkInfo.State.RUNNING -> Log.d("WorkStatus", "任务正在执行")
                WorkInfo.State.SUCCEEDED -> Log.d("WorkStatus", "任务执行成功")
                WorkInfo.State.FAILED -> Log.d("WorkStatus", "任务执行失败")
                else -> Log.d("WorkStatus", "其他状态: ${workInfo.state}")
            }
        }
    })

我个人习惯在 SUCCEEDED 状态时做一些后续操作,比如通知用户、更新 UI。但注意,观察者一定要在 Activity 或 Fragment 的生命周期内注册,否则会内存泄漏。

5. 完整代码示例

把上面几段拼起来,就是一个完整的 WorkManager 任务了。我建议你直接复制到项目里跑一下,感受一下整个流程。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 1. 构建任务
        val workRequest = OneTimeWorkRequestBuilder<SimpleWorker>()
            .build()

        // 2. 加入队列
        val workManager = WorkManager.getInstance(this)
        workManager.enqueue(workRequest)

        // 3. 观察状态
        workManager.getWorkInfoByIdLiveData(workRequest.id)
            .observe(this) { workInfo ->
                Log.d("MainActivity", "任务状态: ${workInfo.state}")
            }
    }
}

避坑指南:

  • 记得在 AndroidManifest.xml 里添加 <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />,如果你的任务需要前台服务。
  • WorkManager 最低支持 API 14,但建议 target API 21+。
  • 调试时可以在 Logcat 里过滤 WorkManager 标签,能看到详细的调度日志。

6. 核心流程一览

为了让你更直观地理解整个流程,我画了一张图。你看一眼就明白了。

WorkManager 第一个任务执行流程 ① 创建 Worker 类 继承 Worker 实现 doWork() ② 构建 WorkRequest OneTimeWorkRequest 设置约束条件 ③ 加入队列 WorkManager .enqueue() ④ 观察状态 getWorkInfoById LiveData / StateFlow 任务状态流转: ENQUEUED → RUNNING → SUCCEEDED / FAILED 如果返回 Result.retry(),会重新进入 ENQUEUED

这张图把整个流程串起来了。你从左边开始,一步步走到右边,再往下看状态。是不是清晰多了?

7. 总结一下

今天我们完成了第一个 WorkManager 任务。你学会了:

  • 如何创建 Worker 类并实现 doWork()
  • 如何构建 OneTimeWorkRequest
  • 如何通过 WorkManager 将任务加入队列
  • 如何观察任务执行状态

说实话,这四步就是 WorkManager 的骨架。后面所有的进阶用法——定时任务、链式任务、约束条件——都是在这个骨架上添砖加瓦。你把这个基础打牢了,后面学起来会非常快。

我的建议:现在就去你的项目里跑一下这个例子。哪怕只是打印一行日志,也比光看不练强一百倍。我记得我第一次跑通时,看到 Logcat 里打出 "任务执行成功",心里那叫一个踏实。

公众号:蓝海资料掘金营,微信deep3321