从 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 版本说明

要将库添加到您的应用,请将以下依赖项添加到您的 build.gradle 文件中:

dependencies {
        def work_version = "2.2.0-beta02"

        // WorkManager library
        implementation "androidx.work:work-runtime:$work_version"

        // Include this library for Kotlin coroutines
        implementation "androidx.work:work-runtime-ktx:$work_version"

        // WorkManager GCM library
        implementation "androidx.work:work-gcm:$work_version"
      }
    

修改清单

在实现 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() requiresCharging()

其他映射

除了限制条件之外,您还可以对 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 对象,您可以将参数作为键值对包含在该对象中。有关详情,请参阅定义任务的输入/输出