从 GCMNetworkManager 迁移到 WorkManager

本文档介绍了如何将应用迁移到使用 WorkManager 客户端库执行后台操作,而不是 GCMNetworkManager 库。应用调度后台作业的首选方式是使用 WorkManager。通过同时包含 WorkManager GCM 库,您可以在 Android 设备运行 API 级别 22 或更低版本时,让 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 库,该库使 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 对象并调用该对象的方法来设置约束(例如,Constraints.Builder.setRequiredNetworkType())),然后使用 Builder 创建一个您可以附加到工作请求的 Constraints 对象。有关更多信息,请参阅定义您的工作请求

GCMNetworkManager 约束 WorkManager 等效项 注意事项
setPersisted() (不需要) 所有 WorkManager 作业在设备重启后都会持久保存
setRequiredNetwork() setRequiredNetworkType() 默认情况下,GCMNetworkManager 需要网络访问。WorkManager 默认不需要网络访问。如果您的作业需要网络访问,您必须使用 setRequiredNetworkType(CONNECTED),或设置更具体的网络类型。
setRequiresCharging()

其他映射

除了约束之外,您还可以将其他设置应用于 GCMNetworkManager 任务。本节列出了将这些设置应用于 WorkManager 作业的相应方法。

标签

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

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

任务参数

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