WorkManager 是什么?
WorkManager 是 Android 用来执行后台任务的工具,适用于:
- 执行一次的任务(比如:上传日志、备份数据)。
- 定期执行的任务(比如:每 15 分钟同步数据)。
- 即使应用关闭、设备重启后也能执行的任务。
1. 引入 WorkManager
先在 build.gradle.kts(模块级)中添加依赖:
dependencies {
implementation("androidx.work:work-runtime-ktx:2.9.0") // WorkManager 最新版
}
然后 同步 Gradle(点击“Sync Now”)。
2. 创建 Worker
Worker 是 WorkManager 执行任务的地方。我们需要创建一个类,继承 Worker 或 CoroutineWorker(推荐)。
简单任务示例
新建一个 MyWorker.kt:
import android.content.Context
import android.util.Log
import androidx.work.Worker
import androidx.work.WorkerParameters
class MyWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
override fun doWork(): Result {
Log.d("MyWorker", "后台任务正在执行...")
// 假设任务执行成功
return Result.success()
}
}
3. 在应用中启动 WorkManager
在 MainActivity.kt 里启动这个任务:
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 创建一个任务
val workRequest = OneTimeWorkRequest.Builder(MyWorker::class.java).build()
// 启动任务
WorkManager.getInstance(this).enqueue(workRequest)
}
}
这样,每次启动应用,WorkManager 就会执行 MyWorker 里的代码。
4. 传递参数
如果 Worker 需要参数,比如下载文件的 URL,可以这样传递:
import androidx.work.Data
val data = Data.Builder()
.putString("url", "https://example.com/file.jpg")
.build()
val workRequest = OneTimeWorkRequest.Builder(MyWorker::class.java)
.setInputData(data) // 传递参数
.build()
WorkManager.getInstance(this).enqueue(workRequest)
然后在 MyWorker 里接收:
override fun doWork(): Result {
val url = inputData.getString("url") ?: "未提供 URL"
Log.d("MyWorker", "下载文件:$url")
return Result.success()
}
5. 周期性任务
如果任务需要定期执行(比如每 15 分钟备份数据),可以用 PeriodicWorkRequest:
import androidx.work.PeriodicWorkRequest
import java.util.concurrent.TimeUnit
val periodicWorkRequest = PeriodicWorkRequest.Builder(MyWorker::class.java, 15, TimeUnit.MINUTES)
.build()
WorkManager.getInstance(this).enqueue(periodicWorkRequest)
⚠️ 注意:最小间隔是 15 分钟,不能更短!
6. 任务约束(例如仅在 WiFi 下运行)
可以加一些条件,比如:
- 只有在 WiFi 连接 时运行。
- 只有在 充电状态 时运行。
import androidx.work.Constraints
import androidx.work.NetworkType
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED) // WiFi 才执行
.setRequiresCharging(true) // 充电时才执行
.build()
val workRequest = OneTimeWorkRequest.Builder(MyWorker::class.java)
.setConstraints(constraints)
.build()
WorkManager.getInstance(this).enqueue(workRequest)
7. 监听任务状态
如果想知道任务是否执行成功,可以这样:
val workManager = WorkManager.getInstance(this)
workManager.getWorkInfoByIdLiveData(workRequest.id).observe(this) { workInfo ->
if (workInfo != null) {
when (workInfo.state) {
WorkInfo.State.ENQUEUED -> Log.d("MyWorker", "任务等待中")
WorkInfo.State.RUNNING -> Log.d("MyWorker", "任务执行中")
WorkInfo.State.SUCCEEDED -> Log.d("MyWorker", "任务成功")
WorkInfo.State.FAILED -> Log.d("MyWorker", "任务失败")
WorkInfo.State.CANCELLED -> Log.d("MyWorker", "任务已取消")
}
}
}
8. 取消任务
可以随时取消任务:
WorkManager.getInstance(this).cancelWorkById(workRequest.id) // 取消某个任务
WorkManager.getInstance(this).cancelAllWork() // 取消所有任务
9. 链式任务(Chained Work)
-
作用: 如果有多个任务需要依次执行,比如先下载数据再处理数据,可以把它们链接起来。
-
简单例子:
val workA = OneTimeWorkRequestBuilder<WorkerA>().build() val workB = OneTimeWorkRequestBuilder<WorkerB>().build() val workC = OneTimeWorkRequestBuilder<WorkerC>().build() WorkManager.getInstance(context) .beginWith(workA) // 先执行 workA .then(workB) // workA 执行完后再执行 workB .then(workC) // workB 执行完后再执行 workC .enqueue() // 提交整个链条任务这样就能保证任务按照你设定的顺序依次完成。
10. 唯一任务(Unique Work)
-
作用: 防止同样的任务重复执行。比如不希望同时有两个相同的任务在运行。
-
简单例子:
val uniqueWorkRequest = OneTimeWorkRequestBuilder<MyWorker>().build() WorkManager.getInstance(context).enqueueUniqueWork( "uniqueTask", // 给任务起一个唯一的名字 ExistingWorkPolicy.REPLACE, // 如果已有同名任务,替换掉旧的任务 uniqueWorkRequest )使用唯一任务可以确保同一时刻不会有多个相同任务重复运行。
总结
| 功能 | 代码 |
|---|---|
| 一次性任务 | OneTimeWorkRequest.Builder(MyWorker::class.java).build() |
| 周期性任务 | PeriodicWorkRequest.Builder(MyWorker::class.java, 15, TimeUnit.MINUTES).build() |
| 传递参数 | Data.Builder().putString("key", "value").build() |
| 添加约束 | Constraints.Builder().setRequiredNetworkType(NetworkType.UNMETERED).build() |
| 监听任务状态 | workManager.getWorkInfoByIdLiveData(id).observe(...) |
| 取消任务 | WorkManager.getInstance(this).cancelWorkById(id) |
适用场景
- 一次性任务(如:上传日志、备份数据库)。
- 定期任务(如:自动同步数据,每天上传一次)。
- 后台任务(如:下载大文件)。
- 任务可以应用退出后执行(如:应用关闭后仍继续备份数据)。
❌ WorkManager 不能做的事情
- 定时精准任务(比如定点 3:00AM 运行,推荐用
AlarmManager)。 - 即时任务(如果任务必须立刻完成,建议用
ForegroundService)。