Миграция с GCMNetworkManager на WorkManager

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

Миграция в WorkManager

Если ваше приложение в настоящее время использует GCMNetworkManager для выполнения фоновых операций, выполните следующие действия для перехода на WorkManager.

Для следующих шагов мы предполагаем, что вы начинаете со следующего кода GCMNetworkManager, который определяет и планирует вашу задачу:

Котлин

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)

Ява

// 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 определяет фактическую операцию загрузки:

Котлин

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

Ява

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 из манифеста.

Определите работника

Ваша реализация GCMNetworkManager определяет OneoffTask или RecurringTask , который определяет, какую работу необходимо выполнить. Вам необходимо переписать его как Worker , как описано в разделе «Определение рабочих запросов» .

Пример кода GCMNetworkManager определяет задачу myTask . Эквивалент WorkManager выглядит следующим образом:

Котлин

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()
    }
}

Ява

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. Создайте OneTimeWorkRequest или PeriodicWorkRequest и установите любые желаемые ограничения, определяющие, когда задача должна выполняться, а также любые теги для идентификации вашей работы.
  2. Передайте запрос в WorkManager.enqueue() , чтобы поставить задачу в очередь на выполнение.

Например, в предыдущем разделе было показано, как преобразовать OneoffTask в эквивалентный Worker . Однако этот Worker не включал ограничения и тег выполнения объекта OneoffTask . Вместо этого мы устанавливаем ограничения и идентификатор задачи при создании WorkRequest . Мы также укажем, что задача не должна запускаться без подключения к сети. Вам не нужно явно запрашивать сетевое подключение с помощью GCMNetworkManager, поскольку GCMNetworkManager требует сетевого подключения по умолчанию, но WorkManager не требует сетевого подключения, если вы специально не добавите это ограничение. После того как мы определили WorkRequest , мы помещаем его в очередь с помощью WorkManager.

Котлин

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

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

Ява

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, содержащий параметры в виде пар ключ/значение. Подробности см. в разделе «Назначение входных данных» .