前言
继上一章《WorkMananger之添加任务》之后,我们再来详细学习任务请求WorkRequest。
构造器
WorkRequest有两种构造器:
OneTimeWorkRequestBuilder<WorkRequest>() 一次性任务构造器
PeriodicWorkRequestBuilder<WorkRequest>() 周期性任务构造器
分别构造两种WorkRequest:
OneTimeWorkRequest 一次性任务
PeriodicWorkRequest 周期性任务
使用示例:
1
2
3
4
5
6
7
|
// 一次性任务
var oneTimeWorkRequest = OneTimeWorkRequestBuilder<MyWorkRequest>()
.builder()
// 每10秒执行一次
var periodicWorkRequest = PeriodicWorkRequestBuilder<MyWorkRequest>(10, TimeUnit.SECONDS)
.builder()
|
周期性任务的时间设置常用方式:
其他方式可自行查阅源码,此处不展开。
约束
设置约束
任务满足约束条件,才会执行
1
2
3
4
5
6
7
8
9
10
|
// 创建约束
val constraints = Constraints.Builder()
.setRequiresDeviceIdle(true)
.setRequiresCharging(true)
.build()
// 设置约束
val compressionWork = OneTimeWorkRequestBuilder<CompressWorker>()
.setConstraints(constraints)
.build()
|
Constraints
包
1
|
androidx.work.Constraints
|
一般约束
包含以下约束方法:
setRequiresDeviceIdle() 设备空闲时运行(Api23及以上)
setRequiresCharging() 正在充电时运行
setRequiredNetworkType() 在特定网络类型下运行
setRequiresBatteryNotLow() 在电量充足时运行
setRequiresStorageNotLow() 在存储空间充足时运行
其他的好理解,网络类型补充说明一下,枚举类NetworkType声明了以下五种网络类型:
NOT_REQUIRED 任务不需要网络
CONNECTED 任务要求连接网络
UNMETERED 任务要求非计量网络(不限量使用的网络,例如包月包年的宽带)
NOT_ROAMING 要求非漫游网络(不是4G、5G之类的,而是连接wifi。别告诉我你手机可能连网线,如果可以那应该也算是非漫游)
METERED 任务要求计量网络(按量收费的网络)
触发器式约束
除了上述约束,Constraints还包含以下一些触发器式的约束:
addContentUriTrigger() 当本地特定的Uri更新时运行(Api24及以上)
setTriggerContentUpdateDelay() 特定内容更新后延迟一段时再运行
setTriggerContentMaxDelay 特定内容更新后最大延迟多少时间再运行
其中setTriggerContentUpdateDelay()和setTriggerContentMaxDelay():
- Api24及以上使用参数
duration(延迟时间)和timeunit(时间单位)
- Api26以上使用参数
duration(延迟时间)
前者规定了延迟时间的下限,后者规定了延迟时间的上限。
延迟时间
设置延迟时间
调用setInitialDelay()设置延迟时间:
1
2
|
// androidx.work.WorkRequest
public @NonNull B setInitialDelay(long duration, @NonNull TimeUnit timeUnit) { ... }
|
使用示例:
1
2
3
|
val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setInitialDelay(10, TimeUnit.MINUTES)
.build()
|
实际延迟时间
结合我们在执行约束中提到的约束,我们可以知道任务实际执行的时间为:初始化延迟+约束延迟
重试与退避政策
设置退避政策
我们在上一章《WorkMananger之添加任务》提到过Worker执行完成后会返回三种状态:
Result.success() 执行成功
Result.failure() 执行失败
Result.retry() 稍后重试
对于Result.retry(),我们可以设置退避政策BackoffPolicy,使得任务暂时退避不执行,等过一段时间后再执行,从而达到“稍后重试”的效果。
调用setBackoffCriteria()来设置BackoffPolicy:
1
2
3
4
5
|
// androidx.work.WorkRequest
public final @NonNull B setBackoffCriteria(
@NonNull BackoffPolicy backoffPolicy,
long backoffDelay,
@NonNull TimeUnit timeUnit)
|
使用示例:
1
2
3
4
5
6
|
val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setBackoffCriteria(
BackoffPolicy.LINEAR,
OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS)
.build()
|
退避政策的时间
退避政策BackoffPolicy是枚举类,包含两种时间延迟方式:
EXPONENTIAL 指数增长型
LINEAR 线性增长型
每次重试失败后,后一次的时间延迟将按BackoffPlicy指定的方式增长。
任务的输入/输出
数据包
任务的输入和输出,使用Data作为数据包,打包的过程由内联函数workOfData。
1
2
3
4
5
6
7
8
|
// androidx.work.Data
inline fun workDataOf(vararg pairs: Pair<String, Any?>): Data {
val dataBuilder = Data.Builder()
for (pair in pairs) {
dataBuilder.put(pair.first, pair.second)
}
return dataBuilder.build()
}
|
设置输入包
我们调用setInputData()来设置数据包:
1
2
|
// androidx.work.WorkRequest
public final @NonNull B setInputData(@NonNull Data inputData) { ... }
|
使用示例:
1
2
3
4
5
|
val imageData = workDataOf(Constants.KEY_IMAGE_URI to imageUriString)
val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setInputData(imageData)
.build()
|
设置输出包
同样使用workOfData来购建Data来作为输出,使用示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class UploadWorker(appContext: Context, workerParams: WorkerParameters)
: Worker(appContext, workerParams) {
override fun doWork(): Result {
// 获得输入
val imageUriInput = getInputData().getString(Constants.KEY_IMAGE_URI)
// TODO:健壮性判断
// 使用输入完成工作
val response = uploadFile(imageUriInput)
// 创建输出
val outputData = workDataOf(Constants.KEY_IMAGE_URL to response.imageUrl)
// 返回输出
return Result.success(outputData)
}
}
|
标记
设置标记
生活中为事物做标记是为了快速找到并了解他们,在这里也是一样,为WorkRequest添加标记是为了方便后续观察他们。
使用addTag()为WorkRequest添加标记:
1
2
3
4
5
|
// androidx.work.WorkRequest
public final @NonNull B addTag(@NonNull String tag) {
mTags.add(tag);
return getThis();
}
|
在WorkRequest中的集合Set<String> mTags用于存储添加的标记。
使用示例:
1
2
3
4
|
val cacheCleanupTask = OneTimeWorkRequestBuilder<CacheCleanupWorker>()
.setConstraints(constraints)
.addTag("cleanup")
.build()
|
取消标记
调用cancelAllWorkByTag()来取消所有带有特定Tag的任务:
1
2
|
// androidx.work.WorkManagerImpl
public @NonNull Operation cancelAllWorkByTag(@NonNull final String tag) { ... }
|
使用示例:
1
|
WorkManager.getInstance(this).cancelAllWorkByTag()
|
关于如何通过标签来观察他们,我们将在后续的章节中陈述。