当前位置:网站首页>WorkManager学习一
WorkManager学习一
2022-07-05 09:49:00 【Mr_Tony】
文章目录
一、前言
目前执行长期的后台任务时候,官方推荐使用WorkManager
来处理后台任务,这里对WorkManager
进行一个简单的记录。WorkManager
主要可以执行以下几种任务
二、添加依赖
dependencies {
val 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"
}
三、简单示例
一个WorkManager
需要三部分组成。定义一个Work
,创建一个WorkRequest
,提交给WorkManager
进行执行。以下是一个简单的一次性任务的示例。
WorkTest.kt
class WorkTest(val appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) {
override fun doWork(): Result {
Log.e("YM--->","后台任务执行中,任务线程:${
Thread.currentThread().id}-->线程名字:${
Thread.currentThread().name}")
return Result.success()
}
}
以下是两种创建WorkRequest
的方式,一种复杂的,一种简单的,根据情况选择一种实现。
private fun initWork() {
// val uploadWorkRequest: WorkRequest = //复杂的构建器方式
// OneTimeWorkRequestBuilder<WorkTest>()
// .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)//设置加急任务
// .build()
val uploadWorkRequest: WorkRequest = OneTimeWorkRequest.from(WorkTest::class.java)//简单方式
WorkManager
.getInstance(this)
.enqueue(periodicWorkRequest)
}
使用WorkManager
进行执行
WorkManager
.getInstance(this)
.enqueue(periodicWorkRequest)
四、定期任务
定期任务可以多次执行一个任务。以下是创建方式
val saveRequest =
PeriodicWorkRequestBuilder<WorkTest>(1, TimeUnit.HOURS)
// Additional configuration
.build()
需要注意下时间,如果时间小于15分钟,则会按照十五分钟进行计算,如果大于十五分钟则按照实际时间计算。
假设想要定义一个灵活的时间段,比如最后十五分钟执行任务,可以使用以下方式
val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
1, TimeUnit.HOURS, // repeatInterval (the period cycle)
15, TimeUnit.MINUTES) // flexInterval
.build()
在创建 PeriodicWorkRequest
时传递 flexInterval
以及 repeatInterval
。灵活时间段从 repeatInterval - flexInterval
开始,一直到间隔结束。
重复间隔必须大于或等于 PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,而灵活间隔必须大于或等于 PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS。
五、工作约束
这里参考官方网站:
约束可确保将工作延迟到满足最佳条件时运行。以下约束适用于 WorkManager。
NetworkType 约束运行工作所需的网络类型。例如 Wi-Fi ( [UNMETERED](https://developer.android.google.cn/reference/androidx/work/NetworkType?hl=zh-cn#UNMETERED)
)。BatteryNotLow 如果设置为 true,那么当设备处于“电量不足模式”时,工作不会运行。 RequiresCharging 如果设置为 true,那么工作只能在设备充电时运行。 DeviceIdle 如果设置为 true,则要求用户的设备必须处于空闲状态,才能运行工作。在运行批量操作时,此约束会非常有用;若是不用此约束,批量操作可能会降低用户设备上正在积极运行的其他应用的性能。 StorageNotLow 如果设置为 true,那么当用户设备上的存储空间不足时,工作不会运行。 如需创建一组约束并将其与某项工作相关联,请使用一个
Contraints.Builder()
创建Constraints
实例,并将该实例分配给WorkRequest.Builder()
。例如,以下代码会构建了一个工作请求,该工作请求仅在用户设备正在充电且连接到 Wi-Fi 网络时才会运行:
val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresCharging(true) .build() val myWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<MyWork>() .setConstraints(constraints) .build()
如果指定了多个约束,工作将仅在满足所有约束时才会运行。
如果在工作运行时不再满足某个约束,WorkManager 将停止工作器。系统将在满足所有约束后重试工作。
六、延迟工作
上面的任务默认来说会立即执行,倘若想要延迟执行的话可以采取以下方式:
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.setInitialDelay(10, TimeUnit.MINUTES)
.build()
需要注意的是定时任务,只有首次会延迟。
七、 重试和重试策略
倘若任务执行失败,想要进行重试,可以使用该方式。重试有两个参数构成:重试时间和重试策略。重试时间是指每次重试前的等待时间,最短10s或者 MIN_BACKOFF_MILLIS。重试策略则是指后续的重试时间以何种方式增涨,有两个参数,一个是线性增涨LINEAR,一个是指数增长EXPONENTIAL。不能设置每次固定的时间。如果使用重试的话,需要在定义 Worker
时候返回Result.retry()
,不能返回Result.success()
。以下是参考代码:
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.setBackoffCriteria(
BackoffPolicy.LINEAR,
OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS)
.build()
八、工作标识
以下参考官网网站:
每个工作请求都可以设置一个唯一标识符,该标识符可用于在以后标识该工作,以便取消工作或观察其进度。
如果有一组在逻辑上相关的工作,对这些工作项进行标记可能也会很有帮助。通过标记,您一起处理一组工作请求。
例如,WorkManager.cancelAllWorkByTag(String) 会取消带有特定标记的所有工作请求,WorkManager.getWorkInfosByTag(String)会返回一个 WorkInfo 对象列表,该列表可用于确定当前工作状态。
以下代码展示了如何向工作添加“cleanup”标记:
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>() .addTag("cleanup") .build()
最后,可以向单个工作请求添加多个标记。这些标记在内部以一组字符串的形式进行存储。您可以使用 WorkInfo.getTags() 获取与
WorkRequest
关联的标记集。从
Worker
类中,您可以通过 ListenableWorker.getTags() 检索其标记集。
九、传递参数
有些工作需要传递一些参数。可以使用以下的方式, 示例代码如下:
// Define the Worker requiring input
class UploadWork(appContext: Context, workerParams: WorkerParameters)
: Worker(appContext, workerParams) {
override fun doWork(): Result {
val imageUriInput =
inputData.getString("IMAGE_URI") ?: return Result.failure()
uploadFile(imageUriInput)
return Result.success()
}
...
}
// Create a WorkRequest for your Worker and sending it input
val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>()
.setInputData(workDataOf(
"IMAGE_URI" to "http://..."
))
.build()
十、加急任务
加急任务据官网说是对那些需要立即执行的任务,比如添加订阅,支付账单,发送消息。但是初步接触,没有发现和其它任务的区别。可能是在WorkManager
有很多任务时候,会导致任务排队,加急任务可以将任务插入到队前进行加快执行。
加急任务是在WorkManager2.7
的时候添加的。并且可能在Android12之前的版本上运行前台服务。所以在一定程度上限制了其使用场景。
以下是引用内容
在 Android 12 之前,工作器中的
getForegroundInfoAsync()
和getForegroundInfo()
方法可让 WorkManager 在您调用setExpedited()
时显示通知。如果您想要请求任务作为加急作业运行,则所有的 ListenableWorker 都必须实现
getForegroundInfo
方法。注意:如果未能实现对应的
getForegroundInfo
方法,那么在旧版平台上调用setExpedited
时,可能会导致运行时崩溃。以 Android 12 或更高版本为目标平台时,前台服务仍然可通过对应的
setForeground
方法使用。注意:
setForeground()
可能会在 Android 12 上抛出运行时异常,并且在启动受到限制时可能会抛出异常。工作器
工作器不知道自身所执行的工作是否已加急。不过,在某些版本的 Android 上,如果
WorkRequest
被加急,工作器可以显示通知。为此,WorkManager 提供了
getForegroundInfoAsync()
方法,您必须实现该方法,让 WorkManager 在必要时显示通知,以便启动ForegroundService
。CoroutineWorker
如果您使用
CoroutineWorker
,则必须实现getForegroundInfo()
。然后,在doWork()
内将其传递给setForeground()
。这样做会在 Android 12 之前的版本中创建通知。请参考以下示例:
class ExpeditedWorker(appContext: Context, workerParams: WorkerParameters): CoroutineWorker(appContext, workerParams) { override suspend fun getForegroundInfo(): ForegroundInfo { return ForegroundInfo( NOTIFICATION_ID, createNotification() ) } override suspend fun doWork(): Result { TODO() } private fun createNotification() : Notification { TODO() }}
注意:您应该将
setForeground()
封装在try/catch
块中,以捕获可能出现的IllegalStateException
。如果您的应用此时无法在前台运行,便可能会发生这类异常。在 Android 12 及更高版本中,您可以使用更详细的ForegroundServiceStartNotAllowedException
。配额政策
您可以控制当应用达到其执行配额时加急工作会发生什么情况。如需继续,您可以传递
setExpedited()
:
OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST
,这会导致作业作为普通工作请求运行。上述代码段演示了此操作。OutOfQuotaPolicy.DROP_WORK_REQUEST
,这会在配额不足时导致请求取消。示例应用
如需查看关于 WorkManager 2.7.0 如何使用加急工作的完整示例,请查看 GitHub 上的 WorkManagerSample。
延迟加急工作
系统会尝试在调用指定的加急作业后,尽快执行该作业。不过,与其他类型的作业一样,系统可能会延迟启动新的加急工作,如在以下情况下:
- 负载:系统负载过高,当有过多作业已在运行或者当系统内存不足时,就会发生这种情况。
- 配额:已超出加急作业配额限制。加急工作使用基于应用待机存储分区的配额系统,并限制滚动时间窗口中的最大执行时间。用于加急工作的配额比用于其他类型的后台作业的配额限制性更强。
需要注意的是,上文继承的Work
类,是ListenableWorker
的子类,所以依然要重写getForegroundInfoAsync()
函数。
十一、参考链接
边栏推荐
- StaticLayout的使用详解
- mysql80服务不启动
- The Alipay in place function can't be found, and the Alipay in place function is offline
- The horizontally scrolling recycleview displays five and a half on one screen, lower than the average distribution of five
- The comparison of every() and some() in JS uses a power storage plan
- 《微信小程序-基础篇》小程序中的事件与冒泡
- 自动化规范检查软件如何发展而来?
- 程序员搞开源,读什么书最合适?
- Design of stepping motor controller based on single chip microcomputer (forward rotation and reverse rotation indicator gear)
- 横向滚动的RecycleView一屏显示五个半,低于五个平均分布
猜你喜欢
Unity粒子特效系列-毒液喷射预制体做好了,unitypackage包直接用 -下
ArcGIS Pro 创建要素
Design and Simulation of fuzzy PID control system for liquid level of double tank (matlab/simulink)
pytorch输出tensor张量时有省略号的解决方案(将tensor完整输出)
Energy momentum: how to achieve carbon neutralization in the power industry?
Have you learned to make money in Dingding, enterprise micro and Feishu?
Uni app running to wechat development tool cannot Preview
MySQL字符类型学习笔记
Events and bubbles in the applet of "wechat applet - Basics"
驱动制造业产业升级新思路的领域知识网络,什么来头?
随机推荐
uniapp + uniCloud+unipay 实现微信小程序支付功能
ConstraintLayout的流式布局Flow
Personal website construction tutorial | local website environment construction | website production tutorial
面试:List 如何根据对象的属性去重?
到底谁才是“良心”国产品牌?
Livedata interview question bank and answers -- 7 consecutive questions in livedata interview~
Fluent development: setting method of left and right alignment of child controls in row
Zblogphp breadcrumb navigation code
【系统设计】指标监控和告警系统
Swift tableview style (I) system basic
Swift uses userdefaults and codable to save an array of class objects or structure instances
Using directive in angualr2 to realize that the picture size changes with the window size
How to use sqlcipher tool to decrypt encrypted database under Windows system
Mysql80 service does not start
A high density 256 channel electrode cap for dry EEG
QT VT100 parser
学习笔记5--高精地图解决方案
How to plan the career of a programmer?
Swift saves an array of class objects with userdefaults and nssecurecoding
一种用于干式脑电图的高密度256通道电极帽