从 GCMNetworkManager 迁移到 WorkManager

本文档说明了如何将应用迁移到使用 WorkManager 客户端库执行后台操作,而不是使用 GCMNetworkManager 库。应用计划后台作业的首选方法是使用 WorkManager。通过同时包含 WorkManager GCM 库,您可以使 WorkManager 在 Android 设备(运行 API 级别 22 或更低版本)上使用 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 库,该库使 WorkManager 能够在您的应用在不支持 JobScheduler 的设备(即运行 API 级别 22 或更低版本的设备)上运行时使用 GCM 进行作业调度。有关添加库的完整详细信息,请参阅 WorkManager 入门

修改您的清单

当您实现 GCMNetworkManager 时,您会将 GcmTaskService 的实例添加到您的应用清单中,如 GcmNetworkManager参考文档 中所述。GcmTaskService 查看传入的任务并将其委托给任务处理程序。WorkManager 管理对您的 Worker 的任务委托,因此您不再需要执行此操作的类;只需从清单中删除您的 GcmTaskService 即可。

定义 Worker

您的 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 约束。本节列出了这些等效项。

通过调用任务的 Builder 对象中的相应方法来设置 GCMNetworkManager 任务上的约束;例如,您可以通过调用Task.Builder.setRequiredNetwork()来设置网络需求。

在 WorkManager 中,您创建一个Constraints.Builder对象并调用该对象的 methods 来设置约束(例如,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 作业设置标签,请在使用该 Builder 创建WorkRequest之前,调用WorkRequest.Builder.addTag()方法。

在 GCMNetworkManager 中,您可以调用setUpdateCurrent()来指定任务是否应替换具有相同标签的任何现有任务。等效的 WorkManager 方法是通过调用enqueueUniqueWork()enqueueUniquePeriodicWork()来排队任务;如果您使用这些方法,则会为作业提供一个唯一名称,并指定如果已存在具有该名称的挂起作业,WorkManager 如何处理该请求。有关更多信息,请参阅处理唯一工作

任务参数

您可以通过调用Task.Builder.setExtras()并传递包含参数的Bundle来将参数传递给 GCMNetworkManager 作业。WorkManager 允许您将Data对象传递给 WorkManager 作业,其中包含参数作为键/值对。有关详细信息,请参阅分配输入数据