Переход с GCMNetworkManager на WorkManager

В этом документе рассказывается, как перевести приложения на использование клиентской библиотеки WorkManager для выполнения фоновых операций вместо библиотеки GCMNetworkManager. Для планирования фоновых задач в приложении рекомендуется использовать WorkManager. Если вы также добавите библиотеку WorkManager GCM, то WorkManager сможет использовать GCM для планирования задач на устройствах Android с API уровня 22 или ниже.

Переход на 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 использовать GCM для планирования заданий, когда приложение запущено на устройствах, не поддерживающих JobScheduler (то есть на устройствах с уровнем API 22 или ниже). Подробные сведения о добавлении библиотек можно найти в статье Начало работы с WorkManager.

Изменение файла манифеста

При реализации GCMNetworkManager вы добавили экземпляр GcmTaskService в манифест приложения, как описано в GcmNetworkManager справочной документации. GcmTaskService проверяет входящую задачу и делегирует ее обработчику задач. WorkManager управляет делегированием задач вашему Worker, поэтому вам больше не нужен класс, который это делает. Просто удалите GcmTaskService из манифеста.

Определение Worker

В реализации GCMNetworkManager определяется OneoffTask или RecurringTask, где указывается, какую именно работу нужно выполнить. Вам нужно переписать его как 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. Worker WorkManager сообщает о результатах с помощью метода ListenableWorker.Result, например ListenableWorker.Result.success(), и возвращает значение этого метода.
  • Как мы уже упоминали, ограничения и теги задаются не при определении Worker, а на следующем шаге, при создании WorkRequest.

Запланируйте запрос на работу

Определяя Worker, вы указываете, что нужно сделать. Чтобы указать, когда должна быть выполнена работа, вам необходимо определить WorkRequest:

  1. Создайте объект OneTimeWorkRequest или PeriodicWorkRequest и задайте нужные ограничения, указав, когда должна выполняться задача, а также теги для идентификации вашей работы.
  2. Передайте запрос в WorkManager.enqueue(), чтобы поставить задачу в очередь на выполнение.

Например, в предыдущем разделе показано, как преобразовать OneoffTask в эквивалентный Worker. Однако в этом объекте Worker не было ограничений на выполнение и тега объекта OneoffTask. Вместо этого мы задаем ограничения и идентификатор задачи при создании WorkRequest. Мы также укажем, что задача не должна выполняться, если нет сетевого подключения. Вам не нужно явно запрашивать сетевое подключение с помощью 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 должна быть строка тега, которая задается с помощью вызова метода setTag() в Builder. Задания WorkManager уникально идентифицируются по идентификатору, который автоматически генерируется WorkManager. Вы можете получить этот идентификатор, вызвав WorkRequest.getId(). Кроме того, у запросов на работу может быть один или несколько тегов. Чтобы задать тег для задачи WorkManager, вызовите метод WorkRequest.Builder.addTag(), прежде чем использовать Builder для создания WorkRequest.

В GCMNetworkManager можно вызвать setUpdateCurrent(), чтобы указать, должна ли задача заменять существующую задачу с тем же тегом. В WorkManager для этого нужно поставить задачу в очередь, вызвав метод enqueueUniqueWork() или enqueueUniquePeriodicWork(). При этом задаче присваивается уникальное название и указывается, как WorkManager должен обрабатывать запрос, если задача с таким названием уже ожидает выполнения. Подробнее об уникальных работах…

Параметры задачи

Чтобы передать параметры в задание GCMNetworkManager, вызовите Task.Builder.setExtras() и передайте Bundle, содержащий параметры. WorkManager позволяет передавать объект Data в задачу WorkManager, содержащую параметры в виде пар "ключ-значение". Подробнее о назначении входных данных…