WorkManager 后台任务
WorkManager 是 Android Jetpack 的一部分,用于处理即使在应用退出或设备重启后仍需运行的可延期异步任务。它会自动根据 API 级别选择最佳实现方式(JobScheduler, Firebase JobDispatcher, AlarmManager)。
适用场景:
- 向后端服务器发送日志或分析数据。
- 定期同步应用数据与服务器。
- 上传图片或视频。
添加依赖
在 build.gradle (Module: app) 中添加:
kotlin
dependencies {
val work_version = "2.9.0"
// Kotlin + Coroutines
implementation("androidx.work:work-runtime-ktx:$work_version")
}定义 Worker
创建一个类继承自 Worker (或 CoroutineWorker 如果使用协程),并重写 doWork() 方法。这是执行后台任务的地方。
kotlin
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
class UploadWorker(appContext: Context, workerParams: WorkerParameters):
Worker(appContext, workerParams) {
override fun doWork(): Result {
// 接收输入数据
val imageUriInput = inputData.getString("IMAGE_URI") ?: return Result.failure()
return try {
// 执行具体的耗时操作,例如上传图片
uploadImage(imageUriInput)
// 返回成功
Result.success()
} catch (throwable: Throwable) {
// 返回失败,也可以返回 Result.retry() 进行重试
Result.failure()
}
}
private fun uploadImage(imageUri: String) {
// 模拟上传逻辑
Thread.sleep(3000)
}
}使用 CoroutineWorker (推荐 Kotlin 用户):
kotlin
class CoroutineUploadWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
// 可以在这里直接调用 suspend 函数
return try {
uploadImageSuspend()
Result.success()
} catch (e: Exception) {
Result.retry()
}
}
}创建 WorkRequest
有两种主要的请求类型:
- OneTimeWorkRequest: 执行一次的任务。
- PeriodicWorkRequest: 定期重复执行的任务。
一次性任务
kotlin
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.workDataOf
// 创建输入数据
val data = workDataOf("IMAGE_URI" to "http://...")
val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setInputData(data) // 传递数据
.build()定期任务
定期任务的时间间隔最少为 15 分钟。
kotlin
import androidx.work.PeriodicWorkRequestBuilder
import java.util.concurrent.TimeUnit
val saveRequest = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)
// .setConstraints(constraints)
.build()加急任务 (Expedited Work)
对于用户急需执行的任务(如发送即时消息),可以使用加急任务。系统会尽可能立即执行。
kotlin
val request = OneTimeWorkRequestBuilder<UploadWorker>()
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()兼容性
加急任务在 Android 12 (API 31) 及更高版本中利用了 JobScheduler 的加急队列。在旧版本中,它会委托给前台服务。因此,你必须在 Worker 中实现 getForegroundInfo() 以提供通知。
添加约束 (Constraints)
你可以指定任务运行的条件,例如仅在连接 Wi-Fi 或充电时运行。
kotlin
import androidx.work.Constraints
import androidx.work.NetworkType
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED) // 仅在不计量网络(Wi-Fi)下运行
.setRequiresCharging(true) // 必须在充电时运行
.build()
val myWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setConstraints(constraints)
.build()提交任务
使用 WorkManager 提交请求。
kotlin
import androidx.work.WorkManager
WorkManager.getInstance(context).enqueue(myWorkRequest)观察任务状态
可以通过 ID 或 Tag 观察任务的状态。
kotlin
WorkManager.getInstance(context).getWorkInfoByIdLiveData(uploadWorkRequest.id)
.observe(this, Observer { workInfo ->
if (workInfo != null && workInfo.state.isFinished) {
// 任务完成
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
// 获取输出数据
val output = workInfo.outputData.getString("KEY")
}
}
})任务链 (Chaining Work)
可以将多个任务串联起来执行。
kotlin
WorkManager.getInstance(context)
.beginWith(filterImageWorker) // 先执行滤镜
.then(compressImageWorker) // 然后压缩
.then(uploadImageWorker) // 最后上传
.enqueue()如果链中的任何任务返回 Result.failure(),整个链将停止执行。
取消任务
kotlin
// 通过 ID 取消
WorkManager.getInstance(context).cancelWorkById(uploadWorkRequest.id)
// 通过 Tag 取消 (如果在创建 Request 时设置了 addTag("syncTag"))
WorkManager.getInstance(context).cancelAllWorkByTag("syncTag")