上周写了一篇Android 12适配笔记,其中有提到Android 12对应用在后台运行时启动ForegroundService做了更严苛的限制,建议使用WorkManager来替代。其实WorkManager早在19年初就推出了第一个稳定版,但是我之前一直没有使用过,正好趁这次机会学习一下。
WorkManager简介
WorkManager是处理后台任务的最新解决方案,最低兼容至Android 4.0,开发时就考虑了对电池续航的影响。不适用于应用关闭时就要终止的后台工作,以及需要立即执行的工作。
WorkManager有许多优点,个人感觉比较重要的有:
- 工作约束条件 可以使用约束条件规定工作运行的最佳场景。例如,仅连接Wifi时、有足够的存储空间时。
- 工作链 可以使用接口来串联各个工作任务,便于控制哪些任务先后执行,哪些任务并行执行。
- 可靠性 已经调度的工作存储在WorkManager内置的Sqlite中,可以确保工作完成,即使中途设备重启,重启设备后WorkManager会自动继续。
WorkManager的简单使用
1. 在项目中引入WorkManager
在项目app module的build.gradle中的dependencies中添加依赖:
dependencies {
def work_version = "2.7.1"
// (Java only)
implementation "androidx.work:work-runtime:$work_version"
// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:$work_version"
// optional - RxJava2 support
implementation "androidx.work:work-rxjava2:$work_version"
// optional - GCMNetworkManager support
implementation "androidx.work:work-gcm:$work_version"
// optional - Test helpers
androidTestImplementation "androidx.work:work-testing:$work_version"
// optional - Multiprocess support
implementation "androidx.work:work-multiprocess:$work_version"
}
2. 定义Worker类
继承Worker类,重写doWork()方法,在doWork()方法中编写需要执行的任务的代码,该方法的返回值会通知WorkManager Service工作是否成功,若失败是否重试。
class UploadWorker(context: Context, workerParameters: WorkerParameters)
: Worker(context, workerParameters) {
override fun doWork(): Result {
//需要执行的任务的代码
//工作完成
return Result.success()
//工作失败
return Result.failure()
//工作失败,进行重试
return Result.retry()
}
}
3. 创建与配置WorkRequest
定义了Worker类之后,通过WorkRequest来定义工作运行的方式和时间。
- 创建WorkRequest WorkRequest分为一次性工作请求(OneTimeWorkRequest)和周期性工作请求(PeriodicWorkRequest):
//一次性工作请求
val oneTimeWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.build()
//周期性工作请求
val periodicWorkRequest: WorkRequest = PeriodicWorkRequestBuilder<UploadWorker>(
//两次工作的间隔时间,时间单位为小时
1, TimeUnit.HOURS,
//临近间隔时间前工作开始的时间,时间单位为分钟
15, TimeUnit.MINUTES
)
.build()
- 创建Constraints(约束条件) 可以对WorkRequest添加以下几种约束条件,当满足条件时,工作才会执行:
val constraints = Constraints.Builder()
//设置网络类型 UNMETERED(Wifi) METERED(流量) NOT_REQUIRED(不限制)
.setRequiredNetworkType(NetworkType.UNMETERED)
//设置电量不足时是否限制运行工作 true(低电量时限制) false (不限制)
.setRequiresBatteryNotLow(true)
//设置是否仅在充电时运行工作 true(仅充电时运行) false(不限制)
.setRequiresCharging(false)
//设置否仅在设备空闲状态时运行工作 true(仅设备空闲时运行) false(不限制)
.setRequiresDeviceIdle(false)
//设置存储空间不足时是否限制运行工作 true(存储空间不足时限制) false(不限制)
.setRequiresStorageNotLow(true)
.build()
val oneTimeWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setConstraints(constraints)
.build()
- 设置延迟时间 使用如下代码来配置工作开始前的延迟时间:
val oneTimeWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
//设置延迟时间,单位为秒
.setInitialDelay(10, TimeUnit.SECONDS)
.build()
- 设置重试参数 使用如下代码来配置工作失败重试的参数:
val oneTimeWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
//设置重试参数
.setBackoffCriteria(
//重试间隔时间的增长模式 LINEAR(如20 30 40)EXPONENTIAL(如 20 40 80)
BackoffPolicy.LINEAR,
//第一次重试的间隔时间
OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
//时间单位
TimeUnit.MILLISECONDS
)
.build()
- 设置工作标签 使用如下方法配置工作的唯一标识,可以用于观察工作进度或取消工作:
val oneTimeWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
//添加唯一标识
.addTag("upload log")
.build()
- 传入参数 如下代码展示了如何配置需要传入到Worker的参数,以及如何获取:
val oneTimeWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
//设置传入的参数
.setInputData(workDataOf("UPLOAD_PATH" to "https://..", "DATA" to "..."))
.build()
class UploadWorker(context: Context, workerParameters: WorkerParameters)
: Worker(context, workerParameters) {
override fun doWork(): Result {
//获取传入的参数
val uploadPath = inputData.getString("UPLOAD_PATH") ?: return Result.failure()
val data = inputData.getString("DATA") ?: return Result.failure()
return Result.success()
}
}
- 提交WorkRequest 使用如下代码提交WorkRequest至WorkManager:
val oneTimeWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.build()
WorkManager.getInstance(this).enqueue(oneTimeWorkRequest)
4. 获取工作的信息
可以通过如下代码来获取工作的信息:
val oneTimeWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.build()
val workInfo = workManager.getWorkInfoById(oneTimeWorkRequest.id).get()
//id
workInfo.id
//状态
workInfo.state
//标签
workInfo.tags
//Result.success() Result.failure() 设置的输出参数
workInfo.outputData
或者可以通过如下代码实时监听工作的状态:
val oneTimeWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.build()
workManager.getWorkInfoByIdLiveData(oneTimeWorkRequest.id).observe(lifecycleOwner, { workInfo ->
//id
workInfo.id
//状态
workInfo.state
//标签
workInfo.tags
//Result.success() Result.failure() 设置的输出参数
workInfo.outputData
})
5. 取消工作
可以通过如下代码取消工作:
val oneTimeWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.build()
//取消指定的worker
workManager.cancelWorkById(oneTimeWorkRequest.id)
//取消所有work
workManager.cancelAllWork()