布景
WorkManager 是google为Android推出Jetpack开发套件的成员之一,是一个持续化作业的引荐处理方案。 咱们在开发过程中一般会遇到一些需求持续化的操作需求,例如,上传文件到服务端,Token过期改写,定时更新服务端下发的装备等。
主要的用处是:
当即开端履行一个使命
有的使命必须当即开端履行,但这儿或许会有个疑问,为什么当即开端履行的使命不直接写代码开端履行,要利用WorkManager呢?这主要归功于WorkManager的一些特性,例如依据束缚安排使命,链式化使命等,让你代码写得更简洁,更好的扩展性。
需求长期定时运转的使命
使命需求长期定时运转的的状况,例如咱们我需求每一个小时上传一次用户日志.
推迟使命
有的使命需求延后一段时刻履行.
再持续讲解它怎么运用之前先来说说它的几个特性.
特性
束缚
供给一些束缚条件去履行使命,当束缚条件满意后才开端履行,例如,当衔接上Wifi, 当设备有满意的电量等条件
可靠性
安排的使命保证能够顺利履行,由于WorkManager内部以SqLite存储使命的履行的状况,为履行的和履行失利的都会从头测验.
加急使命
或许你会给WorkManager安排许多Task, 某些Task也许优先级比较高,需求当即履行,WorkManager供给加急的特性,能够尽早履行这类Task.
链式使命
某些Task或许需求顺序履行,也或许需求并行履行,WorkManager相同供给这类API满意需求
val continuation = WorkManager.getInstance(context)
.beginUniqueWork(
Constants.IMAGE_MANIPULATION_WORK_NAME,
ExistingWorkPolicy.REPLACE,
OneTimeWorkRequest.from(CleanupWorker::class.java)
).then(OneTimeWorkRequest.from(WaterColorFilterWorker::class.java))
.then(OneTimeWorkRequest.from(GrayScaleFilterWorker::class.java))
.then(OneTimeWorkRequest.from(BlurEffectFilterWorker::class.java))
.then(
if (save) {
workRequest<SaveImageToGalleryWorker>(tag = Constants.TAG_OUTPUT)
} else /* upload */ {
workRequest<UploadWorker>(tag = Constants.TAG_OUTPUT)
}
)
线程的互操作性
无缝承继了Coroutines和RxJava的异步特性,在WorkManager也能运用这类异步的API
实战
说了这么多,下面咱们来看看怎么运用WorkManager
第一步,添加依赖
dependencies {
def work_version = "2.8.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"
}
第二步,自界说Worker
这儿咱们需求界说,这个Task需求做什么,创立一个自界说Worker类,这儿咱们创立一个UploadWorker用于做一些后台上传的操作
class UploadWorker(appContext: Context, workerParams: WorkerParameters):
Worker(appContext, workerParams) {
override fun doWork(): Result {
// 做一些上传操作
uploadImages()
// 代表使命履行成功
return Result.success()
}
}
在doWork中咱们能够写上使命需求履行的代码,当使命完毕后需求回来一个Result,这个Result有三个值
Result.success() 使命履行成功
Result.failure() 使命履行失利
Result.retry() 使命需求重试
第三步, 创立一个WorkRequest
当界说完需求做什么后咱们需求创立一个WorkRequest去发动这个使命的履行。WorkManager供给了许多灵敏的API用于界说使命的发动逻辑,例如是否履行一次仍是周期性履行,它的束缚条件是什么等。这儿演示咱们运用OneTimeWorkRequest.
val uploadWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<UploadWorker>()
.build()
第四步, 提交WorkRequest
当创立完成WorkRequest,咱们需求把它交给WorkManager去履行
WorkManager
.getInstance(myContext)
.enqueue(uploadWorkRequest)
进阶
一次性使命
创立一个简略的一次性使命
val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)
假如需求添加一些装备如束缚等能够运用builder
val uploadWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<MyWork>()
// 添加额外装备
.build()
加急作业
WorkManager 履行重要的作业,同时让体系更好地控制对资源的访问。
加急作业具有以下特色:
重要性:加急作业适合对用户重要或由用户发动的使命。
速度:加急作业最适合当即开端并在几分钟内完成的短使命。
配额:束缚前台履行时刻的体系级配额决定加急作业是否能够发动。
电源办理:电源办理束缚(例如省电形式和打瞌睡形式)不太或许影响加急作业。
发动加急作业的方法也十分简略,能够直接调用setExpedited()设置该WorkRequest为一个加急使命
val request = OneTimeWorkRequestBuilder()
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()
WorkManager.getInstance(context)
.enqueue(request)
这儿setExpedited会有一个参数OutOfQuotaPolicy,代表体系配额不足时分,把该使命作为一个一般使命对待.
周期性使命
咱们有一些需求例如,备份运用数据,上传日志,下载一些运用装备,需求周期性进行,咱们能够界说PeriodicWorkRequest去创立周期性的使命.
val saveRequest =
PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)
.build()
上面这段代码每一小时履行一次使命.
可是这个时刻束缚也不是固定的,这儿界说的时刻实际上是最小距离时刻,体系会依据当时体系的状况进行恰当调整。
咱们还能够界说flexInterval让距离提早一点
val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
1, TimeUnit.HOURS, // repeatInterval
15, TimeUnit.MINUTES) // flexInterval
.build()
这样咱们履行使命的时刻是repeatInterval – flexInterval,上面代码的使命会在1小时-15分钟的时分履行.
周期性使命遇上束缚条件
当周期性使命遇到一些束缚条件不满意的时分将会推迟履行,直到束缚条件满意.
关于束缚
WorkManager供给了下列的一些束缚条件.
NetworkType 网络条件束缚,例如只能在衔接WIFI的状况下履行.
BatteryNotLow 非电量低束缚,在有满意的电量的时分履行.
RequiresCharging 需求充电的时分履行束缚
DeviceIdle 在设备无状况时分运转,这样不会对设备的功率产生影响.
StorageNotLow 当设备有有满意的存储空间时分运转
创立一个束缚运用Contraints.Builder()并赋值给WorkRequest.Builder().
下面代码展现创立一个束缚该使命只会在wifi并且在充电的时分履行.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresCharging(true)
.build()
val myWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<MyWork>()
.setConstraints(constraints)
.build()
推迟使命
假如你指定的使命没有束缚或者束缚已经满意,那么它会当即开端履行,假如想让它有个最少的推迟,能够指定一个最小的推迟履行时刻.
下面这个比如展现设置最小10分钟后开端加入行列.
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.setInitialDelay(10, TimeUnit.MINUTES)
.build()
上面展现的针对OneTimeWorkRequestBuilder相同也适用于PeriodicWorkRequest.
退避战略
假如一个使命失利回来Result.retry(), 你的使命能够在稍等进行重试,这种退避战略能够自界说,这儿连个自界说的特点
退避推迟:退避推迟履行下次测验使命的最少时刻,一般咱们自界说最少不能低于[MIN_BACKOFF_MILLIS]
退避战略:退避战略能够指定两种一个是LINEAR(线性)和EXPONENTIAL(幂等)
实际上每一个使命都有一个默认的退避战略,缺省的退避战略是EXPONENTIAL和30s的推迟,可是你能够自界说,下面是一个自界说的比如。
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.setBackoffCriteria(
BackoffPolicy.LINEAR,
OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS)
.build()
Tag使命
每一个使命都能够附加上一个标签,稍后能够运用这个标签找到该使命,撤销它或者检查的履行进展. 假如你有一组使命,能够添加同一个标签,能够统一的操作它们。例如运用WorkManager.cancelAllWorkByTag(String)撤销一切的使命,运用WorkManager.getWorkInfosByTag(String)回来一个使命信息列表检查当时使命的状况.
下面是一个展现给使命赋值一个标签
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.addTag("cleanup")
.build()
链式使命
WorkManager还供给了一种界说顺序履行使命或者并发履行使命的方法。
运用这种方法创立使命通过
WorkManager.beginWith(OneTimeWorkRequest)
WorkManager.beginWith(List<OneTimeWorkRequest>)
以上两个方法都会回来一个WorkContinuation.
WorkContinuation随后能够持续调用
then(OneTimeWorkRequest)
then(List<OneTimeWorkRequest>)
履行链式使命
最后能够调用enqueue()去履行你的作业链. 举个比如
WorkManager.getInstance(myContext)
.beginWith(listOf(plantName1, plantName2, plantName3))
.then(cache)
.then(upload)
.enqueue()
Input Mergers
一个父使命的履行成果能够传递给子使命,例如上面plantName1, plantName2, plantName3履行的成果能够传递
给cache使命,WorkManager运用InputMerger去办理这些多个父使命的输出成果到子使命.
这儿有两种不同类型的的InputMerger
-
OverwritingInputMerger 从输入到输出添加一切的key,遇到抵触的状况,覆盖之前的key的值
-
ArrayCreatingInputMerger 从输入到输出添加一切的key,遇到抵触的状况进行创立数组
作业链的状况
当时面的使命阻塞住的时分后边的使命相同也是阻塞状况.
当时面的使命履行成功后,后边的使命才能持续开端履行
当一个使命失利进行重试的时分并不会影响并发的使命
一个使命失利,后边的使命也会是失利状况
对于撤销也是这样
结语
总的来说WorkManager是一个十分好用的组件,它处理了一些从前实现起来比较繁琐的功用,例如它的束缚履行,咱们能够等待有网络时分履行使命。咱们利用周期性履行使命功用能够很方便的履行一些诸如改写token, 定时日志上传等功用.