定义工作请求

入门指南介绍了如何创建简单的 WorkRequest 并将其加入队列。

在本指南中,您将了解如何自定义工作请求来处理常见用例:

  • 处理网络可用性等任务约束
  • 保证任务执行的延迟时间最短
  • 处理任务重试和退避
  • 处理任务输入和输出
  • 使用标记对任务进行分组

工作约束

您可以向工作添加 Constraints,以指明工作何时可以运行。

例如,您可以指定工作应仅在设备空闲且接通电源时运行。

下面的代码展示了如何将这些约束添加到 OneTimeWorkRequest。有关所支持约束的完整列表,请参阅 Constraints.Builder 参考文档

Kotlin


    // Create a Constraints object that defines when the task should run
    val constraints = Constraints.Builder()
            .setRequiresDeviceIdle(true)
            .setRequiresCharging(true)
            .build()

    // ...then create a OneTimeWorkRequest that uses those constraints
    val compressionWork = OneTimeWorkRequestBuilder<CompressWorker>()
            .setConstraints(constraints)
            .build()

    

Java

    // Create a Constraints object that defines when the task should run
    Constraints constraints = new Constraints.Builder()
        .setRequiresDeviceIdle(true)
        .setRequiresCharging(true)
         .build();

    // ...then create a OneTimeWorkRequest that uses those constraints
    OneTimeWorkRequest compressionWork =
                    new OneTimeWorkRequest.Builder(CompressWorker.class)
         .setConstraints(constraints)
         .build();
    

如果指定了多个约束,您的任务将仅在满足所有约束时才会运行。

如果在任务运行期间某个约束不再得到满足,则 WorkManager 将停止工作器。当约束继续得到满足时,系统将重新尝试执行该任务。

初始延迟

如果您的工作没有约束,或者工作加入队列时所有约束均已得到满足,则系统可能会选择立即运行任务。如果您不希望任务立即运行,则可以将工作指定为在经过最短的初始延迟后启动。

下面的示例展示了如何将任务设置为在加入队列后至少经过 10 分钟再运行。

Kotlin


    val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
            .setInitialDelay(10, TimeUnit.MINUTES)
            .build()

    

Java


    OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class)
            .setInitialDelay(10, TimeUnit.MINUTES)
            .build();

    

重试和退避政策

如果您需要让 WorkManager 重新尝试执行您的任务,可以从工作器返回 Result.retry()

然后,系统会根据默认的退避延迟时间和政策重新调度您的工作。退避延迟时间指定重试工作前的最短等待时间。退避政策定义了在后续重试的尝试过程中,退避延迟时间随时间以怎样的方式增长;默认情况下按 EXPONENTIAL 延长。

以下是自定义退避延迟时间和政策的示例。

Kotlin


    val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
            .setBackoffCriteria(
                    BackoffPolicy.LINEAR,
                    OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                    TimeUnit.MILLISECONDS)
            .build()

    

Java


    OneTimeWorkRequest uploadWorkRequest =
        new OneTimeWorkRequest.Builder(UploadWorker.class)
            .setBackoffCriteria(
                    BackoffPolicy.LINEAR,
                    OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                    TimeUnit.MILLISECONDS)
            .build();
    

定义任务的输入/输出

您的任务可能需要数据以输入参数的形式传入,或者将数据返回为结果。例如,某个任务负责处理图像上传,它要求以要上传的图像的 URI 为输入,并且可能要求用已上传图像的网址作为输出。

输入和输出值以键值对的形式存储在 Data 对象中。下面的代码展示了如何在 WorkRequest 中设置输入数据。

Kotlin


    // workDataOf (part of KTX) converts a list of pairs to a [Data] object.
    val imageData = workDataOf(Constants.KEY_IMAGE_URI to imageUriString)

    val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
            .setInputData(imageData)
            .build()

    

Java


    Data imageData = new Data.Builder
                    .putString(Constants.KEY_IMAGE_URI, imageUriString)
                    .build();

    OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class)
            .setInputData(imageData)
            .build()
    

Worker 类可通过调用 Worker.getInputData() 访问输入参数。

类似地,Data 类可用于输出返回值。要返回 Data 对象,请将它包含到 ResultResult.success()Result.failure() 中,如下所示。

Kotlin

    class UploadWorker(appContext: Context, workerParams: WorkerParameters)
        : Worker(appContext, workerParams) {

        override fun doWork(): Result {

                // Get the input
                val imageUriInput = getInputData().getString(Constants.KEY_IMAGE_URI)
                // TODO: validate inputs.
                // Do the work
                val response = uploadFile(imageUriInput)

                // Create the output of the work
                val outputData = workDataOf(Constants.KEY_IMAGE_URL to response.imageUrl)

                // Return the output
                return Result.success(outputData)

        }
    }

    

Java

    public class UploadWorker extends Worker {

        public UploadWorker(
            @NonNull Context context,
            @NonNull WorkerParameters params) {
            super(context, params);
        }

        @Override
        public Result doWork() {

            // Get the input
            String imageUriInput = getInputData().getString(Constants.KEY_IMAGE_URI)
            // TODO: validate inputs.
            // Do the work
            Response response = uploadFile(imageUriInput)

            // Create the output of the work
            Data outputData = new Data.Builder
                    .putString(Constants.KEY_IMAGE_URL, response.imageUrl)
                    .build();

            // Return the output
            return Result.success(outputData)
        }
    }
    

标记工作

您可以通过为任意 WorkRequest 对象分配标记字符串,按逻辑对任务进行分组。这样您就可以对使用特定标记的所有任务执行操作。

例如,WorkManager.cancelAllWorkByTag(String) 会取消使用特定标记的所有任务,而 WorkManager.getWorkInfosByTagLiveData(String) 会返回 LiveData 和具有该标记的所有任务的状态列表。

以下代码展示了如何使用 WorkRequest.Builder.addTag(String) 向任务添加“cleanup”标记:

Kotlin

    val cacheCleanupTask =
            OneTimeWorkRequestBuilder<CacheCleanupWorker>()
        .setConstraints(constraints)
        .addTag("cleanup")
        .build()
    

Java

    OneTimeWorkRequest cacheCleanupTask =
            new OneTimeWorkRequest.Builder(CacheCleanupWorker.class)
        .setConstraints(constraints)
        .addTag("cleanup")
        .build();