从 GCMNetworkManager 迁移到 WorkManager

本文档介绍如何迁移应用以使用 WorkManager 客户端库而非 GCMNetworkManager 库执行后台操作。应用调度后台作业的首选方法是使用 WorkManager。通过同时包含 WorkManager GCM 库,您可以在运行 API 级别 22 或更低级别的 Android 设备上,允许 WorkManager 使用 GCM 调度任务。

迁移到 WorkManager

如果您的应用目前使用 GCMNetworkManager 执行后台操作,请按照以下步骤迁移到 WorkManager。

对于以下步骤,我们假设您首先使用以下 GCMNetworkManager 代码来定义和调度您的任务:

Kotlin

val myTask = OneoffTask.Builder()
    // setService() says what class does the work
    .setService(MyUploadService::class.java)
    // Don't run the task unless device is charging
    .setRequiresCharging(true)
    // Run the task between 5 & 15 minutes from now
    .setExecutionWindow(5 * DateUtil.MINUTE_IN_SECONDS,
            15 * DateUtil.MINUTE_IN_SECONDS)
    // Define a unique tag for the task
    .setTag("test-upload")
    // ...finally, build the task and assign its value to myTask
    .build()
GcmNetworkManager.getInstance(this).schedule(myTask)

Java

// In GcmNetworkManager, this call defines the task and its
// runtime constraints:
OneoffTask myTask = new OneoffTask.Builder()
    // setService() says what class does the work
    .setService(MyUploadService.class)
    // Don't run the task unless device is charging
    .setRequiresCharging(true)
    // Run the task between 5 & 15 minutes from now
    .setExecutionWindow(
        5 * DateUtil.MINUTE_IN_SECONDS,
        15 * DateUtil.MINUTE_IN_SECONDS)
    // Define a unique tag for the task
    .setTag("test-upload")
    // ...finally, build the task and assign its value to myTask
    .build();
GcmNetworkManager.getInstance(this).schedule(myTask);

在此示例中,我们假设 MyUploadService 定义了实际的上传操作:

Kotlin

class MyUploadService : GcmTaskService() {
    fun onRunTask(params: TaskParams): Int {
        // Do some upload work
        return GcmNetworkManager.RESULT_SUCCESS
    }
}

Java

class MyUploadService extends GcmTaskService {
    @Override
    public int onRunTask(TaskParams params) {
        // Do some upload work
        return GcmNetworkManager.RESULT_SUCCESS;
    }
}

包含 WorkManager 库

如需使用 WorkManager 类,您需要将 WorkManager 库添加到构建依赖项中。您还需要添加 WorkManager GCM 库,当您的应用在不支持 JobScheduler 的设备(即运行 API 级别 22 或更低级别的设备)上运行时,这个库可让 WorkManager 使用 GCM 调度作业。如需了解如何添加库的完整详情,请参阅 WorkManager 使用入门

修改清单

在实现 GCMNetworkManager 时,您按照 GcmNetworkManager 参考文档的说明向应用清单添加了 GcmTaskService 实例。GcmTaskService 会检查传入的任务,然后将其委托给任务处理程序。WorkManager 负责管理指派给您的工作器的任务委托,这样您不必再通过一个类来完成这项任务;只需从清单中移除 GcmTaskService 即可。

定义工作器

您的 GCMNetworkManager 实现会定义 OneoffTaskRecurringTask 来仅指定需要完成的工作。您需要按照定义工作请求中所述,将其重写为 Worker

示例 GCMNetworkManager 代码定义了 myTask 任务。WorkManager 等效代码如下所示:

Kotlin

class UploadWorker(context: Context, params: WorkerParameters)
                        : Worker(context, params) {
    override fun doWork() : Result {
        // Do the upload operation ...
        myUploadOperation()

        // Indicate whether the task finished successfully with the Result
        return Result.success()
    }
}

Java

public class UploadWorker extends Worker {

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

    @Override
    public Result doWork() {
      // Do the upload operation ...

      myUploadOperation()

      // Indicate whether the task finished successfully with the Result
      return Result.success()
    }
}

GCM 任务和 Worker 之间存在一些差异:

  • GCM 使用 TaskParams 对象将参数传递给任务。WorkManager 使用您可以通过 WorkRequest 指定的输入数据,如介绍如何定义任务的输入/输出WorkManager 文档所述。在这两种情况下,您都可以传递键值对来指定任务所需的任何永久性参数。
  • GcmTaskService 通过返回 GcmNetworkManager.RESULT_SUCCESS 之类的标记来指示成功或失败。WorkManager Worker 通过使用 ListenableWorker.Result 方法(例如 ListenableWorker.Result.success())并返回该方法的返回值来指示结果。
  • 正如前文所述,您不需要在定义 Worker 时设置限制条件或标记;而是可以在下一步(即创建 WorkRequest 时)进行设置。

调度工作请求

定义 Worker 可指定您需要执行的任务。如需指定应何时执行工作,需要定义 WorkRequest

  1. 创建 OneTimeWorkRequestPeriodicWorkRequest,并设置用来指定任务应在何时运行的任何所需限制条件,以及用于标识您的工作的任何标记。
  2. 将请求传递到 WorkManager.enqueue(),让任务加入队列以等待执行。

例如,上一部分展示了如何将 OneoffTask 转换为等效的 Worker。但是,Worker 不包含 OneoffTask 对象的执行限制和标记,而是要在创建 WorkRequest 时设置限制条件和任务 ID。我们还要指定,任务必须在有网络连接时才能运行。您无需明确请求与 GCMNetworkManager 建立网络连接,因为 GCMNetworkManager 默认需要网络连接;但 WorkManager 不需要网络连接,除非您明确添加该限制条件。定义了 WorkRequest 之后,我们将其与 WorkManager 一起加入队列。

Kotlin

val uploadConstraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresCharging(true).build()

val uploadTask = OneTimeWorkRequestBuilder<UploadWorker>()
    .setConstraints(uploadConstraints)
    .build()
WorkManager.getInstance().enqueue(uploadTask)

Java

Constraints uploadConstraints = new Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresCharging(true)
    .build();

OneTimeWorkRequest uploadTask =
        new OneTimeWorkRequest.Builder(UploadWorker.class)
  .setConstraints(uploadConstraints)
  .build();
WorkManager.getInstance().enqueue(uploadTask);

API 映射

本部分介绍了如何将某些 GCMNetworkManager 功能和限制条件映射到 WorkManager 等效项。

限制条件映射

GCMNetworkManager 可让您对任务运行时间设置一些限制条件。在大多数情况下,都有明确的 WorkManager 等效限制条件。本部分列出了这些等效限制条件。

对于 GCMNetworkManager 任务,可以在任务的 Builder 对象中调用相应方法来设置其限制条件;例如,您可以调用 Task.Builder.setRequiredNetwork() 来设置网络要求。

在 WorkManager 中,您可以创建 Constraints.Builder 对象并调用该对象的方法来设置限制条件(例如 Constraints.Builder.setRequiredNetworkType())),然后使用 Builder 创建一个 Constraints 对象,您可以将该对象附加到工作请求中。如需了解详情,请参阅定义工作请求

GCMNetworkManager 限制条件 WorkManager 等效功能 备注
setPersisted() (不需要) 所有 WorkManager 作业都会在设备重启后自动保留
setRequiredNetwork() setRequiredNetworkType() 默认情况下,GCMNetworkManager 需要网络访问权限。默认情况下,WorkManager 不需要网络访问权限。如果您的作业需要网络访问权限,则必须使用 setRequiredNetworkType(CONNECTED),或设置更具体的网络类型。
setRequiresCharging()

其他映射

除了限制条件之外,您还可以对 GCMNetworkManager 任务应用一些其他设置。本部分列出了对 WorkManager 作业应用这些设置的相应方法。

标记

所有 GCMNetworkManager 任务都必须有一个标记字符串,您可以调用 Builder 的 setTag() 方法来设置该字符串。WorkManager 作业通过 ID 进行唯一标识,该 ID 由 WorkManager 自动生成;您可以通过调用 WorkRequest.getId() 来获取该 ID。此外,工作请求可以选择性地拥有一个或多个标记。如需为 WorkManager 作业设置标记,请先调用 WorkRequest.Builder.addTag() 方法,再使用该 Builder 创建 WorkRequest

在 GCMNetworkManager 中,您可以调用 setUpdateCurrent() 来指定任务是否应替换具有相同标记的任何现有任务。等效的 WorkManager 方法是通过调用 enqueueUniqueWork()enqueueUniquePeriodicWork() 将任务加入队列的;如果使用这些方法,则需要为作业指定唯一名称,还要指定在存在具有该名称的待处理作业时,WorkManager 应如何处理请求。有关详情,请参阅处理唯一工作

任务参数

您可以通过调用 Task.Builder.setExtras() 并传递包含参数的 Bundle,将参数传递给 GCMNetworkManager 作业。WorkManager 支持向 WorkManager 作业传递 Data 对象,您可以将参数作为键值对包含在该对象中。如需了解详情,请参阅分配输入数据