栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

WorkManager学习一

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

WorkManager学习一

文章目录
  • 一、前言
  • 二、添加依赖
  • 三、简单示例
  • 四、定期任务
  • 五、工作约束
  • 六、延迟工作
  • 七、 重试和重试策略
  • 八、工作标识
  • 九、传递参数
  • 十、加急任务
      • 工作器
      • CoroutineWorker
        • 配额政策
      • 示例应用
      • 延迟加急工作
  • 十一、参考链接

一、前言

目前执行长期的后台任务时候,官方推荐使用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()
//                .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(1, TimeUnit.HOURS)
    // Additional configuration
           .build()

需要注意下时间,如果时间小于15分钟,则会按照十五分钟进行计算,如果大于十五分钟则按照实际时间计算。

假设想要定义一个灵活的时间段,比如最后十五分钟执行任务,可以使用以下方式

val myUploadWork = PeriodicWorkRequestBuilder(
       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()
       .setConstraints(constraints)
       .build()

如果指定了多个约束,工作将仅在满足所有约束时才会运行。

如果在工作运行时不再满足某个约束,WorkManager 将停止工作器。系统将在满足所有约束后重试工作。

六、延迟工作

上面的任务默认来说会立即执行,倘若想要延迟执行的话可以采取以下方式:

val myWorkRequest = OneTimeWorkRequestBuilder()
   .setInitialDelay(10, TimeUnit.MINUTES)
   .build()

需要注意的是定时任务,只有首次会延迟。

七、 重试和重试策略

倘若任务执行失败,想要进行重试,可以使用该方式。重试有两个参数构成:重试时间和重试策略。重试时间是指每次重试前的等待时间,最短10s或者 MIN_BACKOFF_MILLIS。重试策略则是指后续的重试时间以何种方式增涨,有两个参数,一个是线性增涨LINEAR,一个是指数增长EXPONENTIAL。不能设置每次固定的时间。如果使用重试的话,需要在定义 Worker时候返回Result.retry(),不能返回Result.success()。以下是参考代码:

val myWorkRequest = OneTimeWorkRequestBuilder()
   .setBackoffCriteria(
       BackoffPolicy.LINEAR,
       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
       TimeUnit.MILLISECONDS)
   .build()
八、工作标识

以下参考官网网站:

每个工作请求都可以设置一个唯一标识符,该标识符可用于在以后标识该工作,以便取消工作或观察其进度。

如果有一组在逻辑上相关的工作,对这些工作项进行标记可能也会很有帮助。通过标记,您一起处理一组工作请求。

例如,WorkManager.cancelAllWorkByTag(String) 会取消带有特定标记的所有工作请求,WorkManager.getWorkInfosByTag(String)会返回一个 WorkInfo 对象列表,该列表可用于确定当前工作状态。

以下代码展示了如何向工作添加“cleanup”标记:

val myWorkRequest = OneTimeWorkRequestBuilder()
   .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()
   .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()函数。

十一、参考链接
  1. WorkManager 使用入门  |  Android 开发者  |  Android Developers

  2. 应用架构:数据层 - 使用 WorkManager 调度任务 - Android 开发者  |  Android Developers

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1006841.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号