Определите рабочие запросы

В руководстве по началу работы описано, как создать простой WorkRequest и поставить его в очередь.

В этом руководстве вы узнаете, как определять и настраивать объекты WorkRequest для обработки распространенных случаев использования, например, как:

  • Планирование разовых и периодических работ
  • Установите рабочие ограничения, например требование Wi-Fi или зарядки.
  • Гарантируем минимальную задержку выполнения работ
  • Установите стратегии повтора и отсрочки
  • Передача входных данных в работу
  • Групповая совместная работа с использованием тегов

Обзор

Работа определяется в WorkManager через WorkRequest . Чтобы запланировать любую работу с WorkManager, вы должны сначала создать объект WorkRequest , а затем поставить его в очередь.

Котлин

val myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest)

Ява

WorkRequest myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest);

Объект WorkRequest содержит всю информацию, необходимую WorkManager для планирования и выполнения вашей работы. Он включает ограничения, которые должны быть соблюдены для выполнения вашей работы, информацию о планировании, такую ​​как задержки или интервалы повторения, повторную настройку, а также может включать входные данные, если от них зависит ваша работа.

WorkRequest сам по себе является абстрактным базовым классом. Существует две производные реализации этого класса, которые можно использовать для создания запроса: OneTimeWorkRequest и PeriodicWorkRequest . Как следует из их названий, OneTimeWorkRequest полезен для планирования неповторяющейся работы, тогда как PeriodicWorkRequest больше подходит для планирования работы, которая повторяется через определенный интервал.

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

Для простой работы, не требующей дополнительной настройки, используйте статический метод from :

Котлин

val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)

Ява

WorkRequest myWorkRequest = OneTimeWorkRequest.from(MyWork.class);

Для более сложных работ можно использовать конструктор:

Котлин

val uploadWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       // Additional configuration
       .build()

Ява

WorkRequest uploadWorkRequest =
   new OneTimeWorkRequest.Builder(MyWork.class)
       // Additional configuration
       .build();

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

В WorkManager 2.7.0 появилась концепция ускоренной работы. Это позволяет WorkManager выполнять важную работу, одновременно предоставляя системе лучший контроль над доступом к ресурсам.

Ускоренная работа отличается следующими характеристиками:

  • Важность : ускоренная работа подходит для задач, которые важны для пользователя или инициированы пользователем.
  • Скорость : ускоренная работа лучше всего подходит для коротких задач, которые начинаются немедленно и выполняются в течение нескольких минут.
  • Квоты . Квота на уровне системы, ограничивающая время приоритетного выполнения, определяет, может ли быть запущено ускоренное задание.
  • Управление питанием . Ограничения управления питанием , такие как «Экономия заряда» и «Режим сна», с меньшей вероятностью повлияют на ускорение работы.
  • Задержка : система немедленно выполняет ускоренную работу при условии, что текущая рабочая нагрузка системы позволяет это сделать. Это означает, что они чувствительны к задержке и не могут быть запланированы для последующего выполнения.

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

Квоты

Система должна выделить время выполнения ускоренного задания, прежде чем оно сможет запуститься. Срок исполнения не неограничен. Скорее, каждое приложение получает квоту времени выполнения. Когда ваше приложение использует свое время выполнения и достигает выделенной квоты, вы больше не можете выполнять ускоренную работу до тех пор, пока квота не обновится. Это позволяет Android более эффективно балансировать ресурсы между приложениями.

Количество времени выполнения, доступное приложению, зависит от резервного сегмента и важности процесса.

Вы можете определить, что происходит, когда квота выполнения не позволяет выполнить ускоренное задание немедленно. Подробности смотрите в фрагментах ниже.

Выполнение срочной работы

Начиная с WorkManager 2.7, ваше приложение может вызывать setExpedited() чтобы объявить, что WorkRequest должен выполняться как можно быстрее с использованием ускоренного задания. Следующий фрагмент кода представляет собой пример использования setExpedited() :

Котлин

val request = OneTimeWorkRequestBuilder<SyncWorker>()
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build()

WorkManager.getInstance(context)
    .enqueue(request)

Ява

OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>()
    .setInputData(inputData)
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build();

В этом примере мы инициализируем экземпляр OneTimeWorkRequest и вызываем для него setExpedited() . Этот запрос затем становится ускоренной работой. Если квота позволяет, он сразу начнет работать в фоновом режиме. Если квота была использована, параметр OutOfQuotaPolicy указывает, что запрос следует выполнить как обычную несрочную работу.

Обратная совместимость и службы переднего плана

Чтобы обеспечить обратную совместимость для ускоренных заданий, WorkManager может запускать службу переднего плана на версиях платформы старше Android 12. Службы переднего плана могут отображать уведомление пользователю.

Методы getForegroundInfoAsync() и getForegroundInfo() в вашем Worker позволяют WorkManager отображать уведомление при вызове setExpedited() до Android 12.

Любой ListenableWorker должен реализовать метод getForegroundInfo если вы хотите запросить выполнение задачи как ускоренного задания.

При настройке Android 12 или более поздней версии службы переднего плана остаются доступными вам через соответствующий метод setForeground .

Рабочий

Рабочие не знают, ускоряется ли работа, которую они выполняют, или нет. Но в некоторых версиях Android работники могут отображать уведомление об ускорении выполнения WorkRequest .

Чтобы сделать это возможным, WorkManager предоставляет метод getForegroundInfoAsync() , который необходимо реализовать, чтобы WorkManager мог отображать уведомление о запуске ForegroundService , когда это необходимо.

CoroutineWorker

Если вы используете CoroutineWorker , вы должны реализовать getForegroundInfo() . Затем вы передаете его в setForeground() внутри doWork() . Это приведет к созданию уведомления в версиях Android до 12.

Рассмотрим следующий пример:

  class ExpeditedWorker(appContext: Context, workerParams: WorkerParameters):
   CoroutineWorker(appContext, workerParams) {

   override suspend fun getForegroundInfo(): ForegroundInfo {
       return ForegroundInfo(
           NOTIFICATION_ID, createNotification()
       )
   }

   override suspend fun doWork(): Result {
       TODO()
   }

    private fun createNotification() : Notification {
       TODO()
    }

}

Политика квот

Вы можете контролировать, что произойдет с ускоренной работой, когда ваше приложение достигнет квоты выполнения. Чтобы продолжить, вы можете передать setExpedited() :

  • OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST , что приводит к запуску задания как обычного рабочего запроса. Фрагмент выше демонстрирует это.
  • OutOfQuotaPolicy.DROP_WORK_REQUEST , который приводит к отмене запроса, если квоты недостаточно.

Пример приложения

Чтобы увидеть полный пример того, как WorkManager 2.7.0 использует ускоренную работу, просмотрите WorkManagerSample на GitHub.

Отложенная ускоренная работа

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

  • Нагрузка : загрузка системы слишком высока, что может произойти, если уже запущено слишком много заданий или в системе недостаточно памяти.
  • Квота : превышен лимит квоты ускоренных заданий. Ускоренная работа использует систему квот, основанную на сегментах ожидания приложений и ограничивающую максимальное время выполнения в пределах скользящего временного окна. Квоты, используемые для ускоренной работы, более строгие, чем те, которые используются для других типов фоновых задач.

График периодической работы

Иногда вашему приложению может потребоваться периодическое выполнение определенной работы. Например, вы можете периодически создавать резервные копии своих данных, загружать свежий контент в свое приложение или загружать журналы на сервер.

Вот как можно использовать PeriodicWorkRequest для создания объекта WorkRequest , который выполняется периодически:

Котлин

val saveRequest =
       PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)
    // Additional configuration
           .build()

Ява

PeriodicWorkRequest saveRequest =
       new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS)
           // Constraints
           .build();

В этом примере работа запланирована с интервалом в один час.

Интервальный период определяется как минимальное время между повторениями. Точное время выполнения работника зависит от ограничений, которые вы используете в своем объекте WorkRequest, и от оптимизации, выполняемой системой.

Гибкие интервалы запуска

Если характер вашей работы чувствителен к времени выполнения, вы можете настроить PeriodicWorkRequest для выполнения в течение гибкого периода внутри каждого интервала, как показано на рисунке 1.

Вы можете установить гибкий интервал для периодического задания. Вы определяете интервал повторения, и гибкий интервал, который определяет определенное количество времени в конце интервал повторения. WorkManager пытается запустить ваше задание в какой-то момент во время гибкий интервал в каждом цикле.

Рисунок 1. На диаграмме показаны повторяющиеся интервалы с гибким периодом, в течение которого может выполняться работа.

Чтобы определить периодическую работу с гибким периодом, вы передаете flexInterval вместе с repeatInterval при создании PeriodicWorkRequest . Период гибкости начинается с repeatInterval - flexInterval и продолжается до конца интервала.

Ниже приведен пример периодической работы, которая может выполняться в течение последних 15 минут каждого часового периода.

Котлин

val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
       1, TimeUnit.HOURS, // repeatInterval (the period cycle)
       15, TimeUnit.MINUTES) // flexInterval
    .build()

Ява

WorkRequest saveRequest =
       new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class,
               1, TimeUnit.HOURS,
               15, TimeUnit.MINUTES)
           .build();

Интервал повторения должен быть больше или равен PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS , а гибкий интервал должен быть больше или равен PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS .

Влияние ограничений на периодическую работу

Вы можете применять ограничения к периодической работе. Например, вы можете добавить ограничение к вашему рабочему запросу, чтобы работа выполнялась только тогда, когда устройство пользователя заряжается. В этом случае, даже если определенный интервал повторения пройдет, PeriodicWorkRequest не будет запущен до тех пор, пока не будет выполнено это условие. Это может привести к задержке или даже пропуску определенного выполнения вашей работы, если условия не будут выполнены в течение интервала выполнения.

Ограничения по работе

Ограничения гарантируют, что работа будет отложена до тех пор, пока не будут достигнуты оптимальные условия. Следующие ограничения доступны WorkManager.

Тип сети Ограничивает тип сети, необходимой для работы вашей работы. Например, Wi-Fi ( UNMETERED ).
БатареяNotLow Если установлено значение true, ваша работа не будет работать, если устройство находится в режиме низкого заряда батареи.
Требует зарядки Если установлено значение true, ваша работа будет выполняться только во время зарядки устройства.
Устройство в режиме ожидания Если установлено значение true, перед запуском работы устройство пользователя должно находиться в режиме ожидания. Это может быть полезно для выполнения пакетных операций, которые в противном случае могли бы отрицательно повлиять на производительность других приложений, активно работающих на устройстве пользователя.
ХранениеNotLow Если установлено значение true, ваша работа не будет выполняться, если на устройстве пользователя слишком мало места для хранения данных.

Чтобы создать набор ограничений и связать его с некоторой работой, создайте экземпляр Constraints с помощью Contraints.Builder() и назначьте его вашему WorkRequest.Builder() .

Например, следующий код создает рабочий запрос, который выполняется только тогда, когда устройство пользователя заряжается и подключено к Wi-Fi:

Котлин

val constraints = Constraints.Builder()
   .setRequiredNetworkType(NetworkType.UNMETERED)
   .setRequiresCharging(true)
   .build()

val myWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       .setConstraints(constraints)
       .build()

Ява

Constraints constraints = new Constraints.Builder()
       .setRequiredNetworkType(NetworkType.UNMETERED)
       .setRequiresCharging(true)
       .build();

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
               .setConstraints(constraints)
               .build();

Если указано несколько ограничений, ваша работа будет выполняться только тогда, когда все ограничения будут выполнены.

В случае, если ограничение не будет выполнено во время выполнения вашей работы, WorkManager остановит вашего исполнителя. Затем работа будет повторена, когда все ограничения будут выполнены.

Отложенная работа

В случае, если ваша работа не имеет ограничений или все ограничения соблюдены, когда ваша работа поставлена ​​в очередь, система может принять решение о немедленном запуске работы. Если вы не хотите, чтобы работа запускалась немедленно, вы можете указать, что работа начнется после минимальной начальной задержки.

Вот пример того, как настроить выполнение вашей работы не менее чем через 10 минут после ее постановки в очередь.

Котлин

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setInitialDelay(10, TimeUnit.MINUTES)
   .build()

Ява

WorkRequest myWorkRequest =
      new OneTimeWorkRequest.Builder(MyWork.class)
               .setInitialDelay(10, TimeUnit.MINUTES)
               .build();

Хотя в примере показано, как установить начальную задержку для OneTimeWorkRequest , вы также можете установить начальную задержку для PeriodicWorkRequest . В этом случае будет отложен только первый запуск вашей периодической работы.

Политика повторных попыток и отсрочки

Если вам требуется, чтобы WorkManager повторил вашу работу, вы можете вернуть Result.retry() от своего работника. Затем ваша работа переносится в соответствии с задержкой отсрочки и политикой отсрочки .

  • Задержка отсрочки определяет минимальное время ожидания перед повторной попыткой работы после первой попытки. Это значение может быть не менее 10 секунд (или MIN_BACKOFF_MILLIS ).

  • Политика отсрочки определяет, как задержка отсрочки должна увеличиваться с течением времени для последующих повторных попыток. WorkManager поддерживает две политики отсрочки: LINEAR и EXPONENTIAL .

Каждый запрос на работу имеет политику отсрочки и задержку отсрочки. Политика по умолчанию — EXPONENTIAL с задержкой 30 секунд, но вы можете переопределить ее в конфигурации вашего рабочего запроса.

Ниже приведен пример настройки задержки и политики отсрочки.

Котлин

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setBackoffCriteria(
       BackoffPolicy.LINEAR,
       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
       TimeUnit.MILLISECONDS)
   .build()

Ява

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
               .setBackoffCriteria(
                       BackoffPolicy.LINEAR,
                       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                       TimeUnit.MILLISECONDS)
               .build();

В этом примере минимальная задержка отсрочки установлена ​​на минимально допустимое значение, 10 секунд. Поскольку политика LINEAR интервал повтора будет увеличиваться примерно на 10 секунд с каждой новой попыткой. Например, первая попытка завершения с помощью Result.retry() будет предпринята снова через 10 секунд, а затем через 20, 30, 40 и т. д., если работа продолжает возвращать Result.retry() после последующих попыток. Если бы для политики отсрочки было установлено значение EXPONENTIAL , продолжительность повторных попыток была бы ближе к 20, 40, 80 и т. д.

Работа с тегами

Каждый запрос на работу имеет уникальный идентификатор , который можно использовать для идентификации этой работы позже, чтобы отменить работу или наблюдать за ее ходом .

Если у вас есть группа логически связанных работ, вам также может оказаться полезным пометить эти рабочие элементы тегами. Маркировка позволяет работать с группой рабочих запросов вместе.

Например, WorkManager.cancelAllWorkByTag(String) отменяет все рабочие запросы с определенным тегом, а WorkManager.getWorkInfosByTag(String) возвращает список объектов WorkInfo, которые можно использовать для определения текущего рабочего состояния.

Следующий код показывает, как можно добавить тег «очистки» к своей работе:

Котлин

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .addTag("cleanup")
   .build()

Ява

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
       .addTag("cleanup")
       .build();

Наконец, к одному рабочему запросу можно добавить несколько тегов. Внутри эти теги хранятся в виде набора строк. Чтобы получить набор тегов, связанных с WorkRequest вы можете использовать WorkInfo.getTags() .

Из вашего класса Worker вы можете получить набор тегов с помощью ListenableWorker.getTags() .

Назначить входные данные

Для выполнения вашей работы могут потребоваться входные данные. Например, работа по загрузке изображения может потребовать загрузки URI изображения в качестве входных данных.

Входные значения хранятся в виде пар ключ-значение в объекте Data и могут быть установлены в рабочем запросе. WorkManager доставит входные Data в вашу работу при ее выполнении. Класс Worker может получить доступ к входным аргументам, вызвав Worker.getInputData() . В приведенном ниже коде показано, как создать экземпляр Worker , которому требуются входные данные, и как отправить его в рабочий запрос.

Котлин

// Define the Worker requiring input
class UploadWork(appContext: Context, workerParams: WorkerParameters)
   : Worker(appContext, workerParams) {

   override fun doWork(): Result {
       val imageUriInput =
           inputData.getString("IMAGE_URI") ?: return Result.failure()

       uploadFile(imageUriInput)
       return Result.success()
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>()
   .setInputData(workDataOf(
       "IMAGE_URI" to "http://..."
   ))
   .build()

Ява

// Define the Worker requiring input
public class UploadWork extends Worker {

   public UploadWork(Context appContext, WorkerParameters workerParams) {
       super(appContext, workerParams);
   }

   @NonNull
   @Override
   public Result doWork() {
       String imageUriInput = getInputData().getString("IMAGE_URI");
       if(imageUriInput == null) {
           return Result.failure();
       }

       uploadFile(imageUriInput);
       return Result.success();
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
WorkRequest myUploadWork =
      new OneTimeWorkRequest.Builder(UploadWork.class)
           .setInputData(
               new Data.Builder()
                   .putString("IMAGE_URI", "http://...")
                   .build()
           )
           .build();

Аналогичным образом класс Data можно использовать для вывода возвращаемого значения. Входные и выходные данные более подробно рассмотрены в разделе «Входные параметры и возвращаемые значения» .

Следующие шаги

На странице «Состояния и наблюдение» вы узнаете больше о рабочих состояниях и о том, как отслеживать ход своей работы.

,

В руководстве по началу работы описано, как создать простой WorkRequest и поставить его в очередь.

В этом руководстве вы узнаете, как определять и настраивать объекты WorkRequest для обработки распространенных случаев использования, например, как:

  • Планирование разовых и периодических работ
  • Установите рабочие ограничения, например требование Wi-Fi или зарядки.
  • Гарантируем минимальную задержку выполнения работ
  • Установите стратегии повтора и отсрочки
  • Передача входных данных в работу
  • Групповая совместная работа с использованием тегов

Обзор

Работа определяется в WorkManager через WorkRequest . Чтобы запланировать любую работу с WorkManager, вы должны сначала создать объект WorkRequest , а затем поставить его в очередь.

Котлин

val myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest)

Ява

WorkRequest myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest);

Объект WorkRequest содержит всю информацию, необходимую WorkManager для планирования и выполнения вашей работы. Он включает ограничения, которые должны быть соблюдены для выполнения вашей работы, информацию о планировании, такую ​​как задержки или интервалы повторения, повторную настройку, а также может включать входные данные, если от них зависит ваша работа.

WorkRequest сам по себе является абстрактным базовым классом. Существует две производные реализации этого класса, которые можно использовать для создания запроса: OneTimeWorkRequest и PeriodicWorkRequest . Как следует из их названий, OneTimeWorkRequest полезен для планирования неповторяющейся работы, тогда как PeriodicWorkRequest больше подходит для планирования работы, которая повторяется через определенный интервал.

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

Для простой работы, не требующей дополнительной настройки, используйте статический метод from :

Котлин

val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)

Ява

WorkRequest myWorkRequest = OneTimeWorkRequest.from(MyWork.class);

Для более сложных работ можно использовать конструктор:

Котлин

val uploadWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       // Additional configuration
       .build()

Ява

WorkRequest uploadWorkRequest =
   new OneTimeWorkRequest.Builder(MyWork.class)
       // Additional configuration
       .build();

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

В WorkManager 2.7.0 появилась концепция ускоренной работы. Это позволяет WorkManager выполнять важную работу, одновременно предоставляя системе лучший контроль над доступом к ресурсам.

Ускоренная работа отличается следующими характеристиками:

  • Важность : ускоренная работа подходит для задач, которые важны для пользователя или инициированы пользователем.
  • Скорость : ускоренная работа лучше всего подходит для коротких задач, которые начинаются немедленно и выполняются в течение нескольких минут.
  • Квоты . Квота на уровне системы, ограничивающая время приоритетного выполнения, определяет, может ли быть запущено ускоренное задание.
  • Управление питанием . Ограничения управления питанием , такие как «Экономия заряда» и «Режим сна», с меньшей вероятностью повлияют на ускорение работы.
  • Задержка : система немедленно выполняет ускоренную работу при условии, что текущая рабочая нагрузка системы позволяет это сделать. Это означает, что они чувствительны к задержке и не могут быть запланированы для последующего выполнения.

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

Квоты

Система должна выделить время выполнения ускоренного задания, прежде чем оно сможет запуститься. Срок исполнения не неограничен. Скорее, каждое приложение получает квоту времени выполнения. Когда ваше приложение использует свое время выполнения и достигает выделенной квоты, вы больше не можете выполнять ускоренную работу до тех пор, пока квота не обновится. Это позволяет Android более эффективно балансировать ресурсы между приложениями.

Количество времени выполнения, доступное приложению, зависит от резервного сегмента и важности процесса.

Вы можете определить, что происходит, когда квота выполнения не позволяет выполнить ускоренное задание немедленно. Подробности смотрите в фрагментах ниже.

Выполнение срочной работы

Начиная с WorkManager 2.7, ваше приложение может вызывать setExpedited() чтобы объявить, что WorkRequest должен выполняться как можно быстрее с использованием ускоренного задания. Следующий фрагмент кода представляет собой пример использования setExpedited() :

Котлин

val request = OneTimeWorkRequestBuilder<SyncWorker>()
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build()

WorkManager.getInstance(context)
    .enqueue(request)

Ява

OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>()
    .setInputData(inputData)
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build();

В этом примере мы инициализируем экземпляр OneTimeWorkRequest и вызываем для него setExpedited() . Этот запрос затем становится ускоренной работой. Если квота позволяет, он сразу начнет работать в фоновом режиме. Если квота была использована, параметр OutOfQuotaPolicy указывает, что запрос следует выполнить как обычную несрочную работу.

Обратная совместимость и службы переднего плана

Чтобы обеспечить обратную совместимость для ускоренных заданий, WorkManager может запускать службу переднего плана на версиях платформы старше Android 12. Службы переднего плана могут отображать уведомление пользователю.

Методы getForegroundInfoAsync() и getForegroundInfo() в вашем Worker позволяют WorkManager отображать уведомление при вызове setExpedited() до Android 12.

Любой ListenableWorker должен реализовать метод getForegroundInfo если вы хотите запросить выполнение задачи как ускоренного задания.

При настройке Android 12 или более поздней версии службы переднего плана остаются доступными вам через соответствующий метод setForeground .

Рабочий

Рабочие не знают, ускоряется ли работа, которую они выполняют, или нет. Но в некоторых версиях Android работники могут отображать уведомление об ускорении выполнения WorkRequest .

Чтобы сделать это возможным, WorkManager предоставляет метод getForegroundInfoAsync() , который необходимо реализовать, чтобы WorkManager мог отображать уведомление о запуске ForegroundService , когда это необходимо.

CoroutineWorker

Если вы используете CoroutineWorker , вы должны реализовать getForegroundInfo() . Затем вы передаете его в setForeground() внутри doWork() . Это приведет к созданию уведомления в версиях Android до 12.

Рассмотрим следующий пример:

  class ExpeditedWorker(appContext: Context, workerParams: WorkerParameters):
   CoroutineWorker(appContext, workerParams) {

   override suspend fun getForegroundInfo(): ForegroundInfo {
       return ForegroundInfo(
           NOTIFICATION_ID, createNotification()
       )
   }

   override suspend fun doWork(): Result {
       TODO()
   }

    private fun createNotification() : Notification {
       TODO()
    }

}

Политика квот

Вы можете контролировать, что произойдет с ускоренной работой, когда ваше приложение достигнет квоты выполнения. Чтобы продолжить, вы можете передать setExpedited() :

  • OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST , что приводит к запуску задания как обычного рабочего запроса. Фрагмент выше демонстрирует это.
  • OutOfQuotaPolicy.DROP_WORK_REQUEST , который приводит к отмене запроса, если квоты недостаточно.

Пример приложения

Чтобы увидеть полный пример того, как WorkManager 2.7.0 использует ускоренную работу, просмотрите WorkManagerSample на GitHub.

Отложенная ускоренная работа

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

  • Нагрузка : загрузка системы слишком высока, что может произойти, если уже запущено слишком много заданий или в системе недостаточно памяти.
  • Квота : превышен лимит квоты ускоренных заданий. Ускоренная работа использует систему квот, основанную на сегментах ожидания приложений и ограничивающую максимальное время выполнения в пределах скользящего временного окна. Квоты, используемые для ускоренной работы, более строгие, чем те, которые используются для других типов фоновых задач.

График периодической работы

Иногда вашему приложению может потребоваться периодическое выполнение определенной работы. Например, вы можете периодически создавать резервные копии своих данных, загружать свежий контент в свое приложение или загружать журналы на сервер.

Вот как можно использовать PeriodicWorkRequest для создания объекта WorkRequest , который выполняется периодически:

Котлин

val saveRequest =
       PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)
    // Additional configuration
           .build()

Ява

PeriodicWorkRequest saveRequest =
       new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS)
           // Constraints
           .build();

В этом примере работа запланирована с интервалом в один час.

Интервальный период определяется как минимальное время между повторениями. Точное время выполнения работника зависит от ограничений, которые вы используете в своем объекте WorkRequest, и от оптимизации, выполняемой системой.

Гибкие интервалы запуска

Если характер вашей работы чувствителен к времени выполнения, вы можете настроить PeriodicWorkRequest для выполнения в течение гибкого периода внутри каждого интервала, как показано на рисунке 1.

Вы можете установить гибкий интервал для периодического задания. Вы определяете интервал повторения, и гибкий интервал, который определяет определенное количество времени в конце интервал повторения. WorkManager пытается запустить ваше задание в какой-то момент во время гибкий интервал в каждом цикле.

Рисунок 1. На диаграмме показаны повторяющиеся интервалы с гибким периодом, в течение которого может выполняться работа.

Чтобы определить периодическую работу с гибким периодом, вы передаете flexInterval вместе с repeatInterval при создании PeriodicWorkRequest . Период гибкости начинается с repeatInterval - flexInterval и продолжается до конца интервала.

Ниже приведен пример периодической работы, которая может выполняться в течение последних 15 минут каждого часового периода.

Котлин

val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
       1, TimeUnit.HOURS, // repeatInterval (the period cycle)
       15, TimeUnit.MINUTES) // flexInterval
    .build()

Ява

WorkRequest saveRequest =
       new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class,
               1, TimeUnit.HOURS,
               15, TimeUnit.MINUTES)
           .build();

Интервал повторения должен быть больше или равен PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS , а гибкий интервал должен быть больше или равен PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS .

Влияние ограничений на периодическую работу

Вы можете применять ограничения к периодической работе. Например, вы можете добавить ограничение к вашему рабочему запросу, чтобы работа выполнялась только тогда, когда устройство пользователя заряжается. В этом случае, даже если определенный интервал повторения пройдет, PeriodicWorkRequest не будет запущен до тех пор, пока не будет выполнено это условие. Это может привести к задержке или даже пропуску определенного выполнения вашей работы, если условия не будут выполнены в течение интервала выполнения.

Ограничения по работе

Ограничения гарантируют, что работа откладывается до тех пор, пока не будут достигнуты оптимальные условия. Следующие ограничения доступны WorkManager.

Тип сети Ограничивает тип сети, необходимой для работы вашей работы. Например, Wi-Fi ( UNMETERED ).
БатареяNotLow Если установлено значение true, ваша работа не будет работать, если устройство находится в режиме низкого заряда батареи.
Требует зарядки Если установлено значение true, ваша работа будет выполняться только во время зарядки устройства.
Устройство в режиме ожидания Если установлено значение true, перед запуском работы устройство пользователя должно находиться в режиме ожидания. Это может быть полезно для выполнения пакетных операций, которые в противном случае могли бы отрицательно повлиять на производительность других приложений, активно работающих на устройстве пользователя.
ХранениеNotLow Если установлено значение true, ваша работа не будет выполняться, если на устройстве пользователя слишком мало места для хранения данных.

Чтобы создать набор ограничений и связать его с некоторой работой, создайте экземпляр Constraints с помощью Contraints.Builder() и назначьте его вашему WorkRequest.Builder() .

Например, следующий код создает рабочий запрос, который выполняется только тогда, когда устройство пользователя заряжается и подключено к Wi-Fi:

Котлин

val constraints = Constraints.Builder()
   .setRequiredNetworkType(NetworkType.UNMETERED)
   .setRequiresCharging(true)
   .build()

val myWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       .setConstraints(constraints)
       .build()

Ява

Constraints constraints = new Constraints.Builder()
       .setRequiredNetworkType(NetworkType.UNMETERED)
       .setRequiresCharging(true)
       .build();

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
               .setConstraints(constraints)
               .build();

Если указано несколько ограничений, ваша работа будет выполняться только тогда, когда все ограничения будут выполнены.

Если ограничение не будет выполнено во время выполнения вашей работы, WorkManager остановит вашего исполнителя. Затем работа будет повторена, когда все ограничения будут выполнены.

Отложенная работа

В случае, если ваша работа не имеет ограничений или все ограничения соблюдены, когда ваша работа поставлена ​​в очередь, система может принять решение о немедленном запуске работы. Если вы не хотите, чтобы работа запускалась немедленно, вы можете указать, что работа начнется после минимальной начальной задержки.

Вот пример того, как настроить выполнение вашей работы не менее чем через 10 минут после ее постановки в очередь.

Котлин

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setInitialDelay(10, TimeUnit.MINUTES)
   .build()

Ява

WorkRequest myWorkRequest =
      new OneTimeWorkRequest.Builder(MyWork.class)
               .setInitialDelay(10, TimeUnit.MINUTES)
               .build();

Хотя в примере показано, как установить начальную задержку для OneTimeWorkRequest , вы также можете установить начальную задержку для PeriodicWorkRequest . В этом случае будет отложен только первый запуск вашей периодической работы.

Политика повторных попыток и отсрочки

Если вам требуется, чтобы WorkManager повторил вашу работу, вы можете вернуть Result.retry() от своего работника. Затем ваша работа переносится в соответствии с задержкой отсрочки и политикой отсрочки .

  • Задержка отсрочки определяет минимальное время ожидания перед повторной попыткой работы после первой попытки. Это значение может быть не менее 10 секунд (или MIN_BACKOFF_MILLIS ).

  • Политика отсрочки определяет, как задержка отсрочки должна увеличиваться с течением времени для последующих повторных попыток. WorkManager поддерживает две политики отсрочки: LINEAR и EXPONENTIAL .

Каждый запрос на работу имеет политику отсрочки и задержку отсрочки. Политика по умолчанию — EXPONENTIAL с задержкой 30 секунд, но вы можете переопределить ее в конфигурации вашего рабочего запроса.

Ниже приведен пример настройки задержки и политики отсрочки.

Котлин

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setBackoffCriteria(
       BackoffPolicy.LINEAR,
       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
       TimeUnit.MILLISECONDS)
   .build()

Ява

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
               .setBackoffCriteria(
                       BackoffPolicy.LINEAR,
                       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                       TimeUnit.MILLISECONDS)
               .build();

В этом примере минимальная задержка отсрочки установлена ​​на минимально допустимое значение, 10 секунд. Поскольку политика LINEAR интервал повтора будет увеличиваться примерно на 10 секунд с каждой новой попыткой. Например, первая попытка завершения с помощью Result.retry() будет предпринята снова через 10 секунд, а затем через 20, 30, 40 и т. д., если работа продолжает возвращать Result.retry() после последующих попыток. Если бы для политики отсрочки было установлено значение EXPONENTIAL , продолжительность повторных попыток была бы ближе к 20, 40, 80 и т. д.

Работа с тегами

Каждый запрос на работу имеет уникальный идентификатор , который можно использовать для идентификации этой работы позже, чтобы отменить работу или наблюдать за ее ходом .

Если у вас есть группа логически связанных работ, вам также может оказаться полезным пометить эти рабочие элементы тегами. Маркировка позволяет работать с группой рабочих запросов вместе.

Например, WorkManager.cancelAllWorkByTag(String) отменяет все рабочие запросы с определенным тегом, а WorkManager.getWorkInfosByTag(String) возвращает список объектов WorkInfo, которые можно использовать для определения текущего рабочего состояния.

Следующий код показывает, как можно добавить тег «очистки» к своей работе:

Котлин

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .addTag("cleanup")
   .build()

Ява

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
       .addTag("cleanup")
       .build();

Наконец, к одному рабочему запросу можно добавить несколько тегов. Внутри эти теги хранятся в виде набора строк. Чтобы получить набор тегов, связанных с WorkRequest вы можете использовать WorkInfo.getTags() .

Из вашего класса Worker вы можете получить набор тегов с помощью ListenableWorker.getTags() .

Назначить входные данные

Для выполнения вашей работы могут потребоваться входные данные. Например, работа по загрузке изображения может потребовать загрузки URI изображения в качестве входных данных.

Входные значения хранятся в виде пар ключ-значение в объекте Data и могут быть установлены в рабочем запросе. WorkManager доставит входные Data в вашу работу при ее выполнении. Класс Worker может получить доступ к входным аргументам, вызвав Worker.getInputData() . В приведенном ниже коде показано, как создать экземпляр Worker , которому требуются входные данные, и как отправить его в рабочий запрос.

Котлин

// Define the Worker requiring input
class UploadWork(appContext: Context, workerParams: WorkerParameters)
   : Worker(appContext, workerParams) {

   override fun doWork(): Result {
       val imageUriInput =
           inputData.getString("IMAGE_URI") ?: return Result.failure()

       uploadFile(imageUriInput)
       return Result.success()
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>()
   .setInputData(workDataOf(
       "IMAGE_URI" to "http://..."
   ))
   .build()

Ява

// Define the Worker requiring input
public class UploadWork extends Worker {

   public UploadWork(Context appContext, WorkerParameters workerParams) {
       super(appContext, workerParams);
   }

   @NonNull
   @Override
   public Result doWork() {
       String imageUriInput = getInputData().getString("IMAGE_URI");
       if(imageUriInput == null) {
           return Result.failure();
       }

       uploadFile(imageUriInput);
       return Result.success();
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
WorkRequest myUploadWork =
      new OneTimeWorkRequest.Builder(UploadWork.class)
           .setInputData(
               new Data.Builder()
                   .putString("IMAGE_URI", "http://...")
                   .build()
           )
           .build();

Аналогичным образом класс Data можно использовать для вывода возвращаемого значения. Входные и выходные данные более подробно рассмотрены в разделе «Входные параметры и возвращаемые значения» .

Следующие шаги

На странице «Состояния и наблюдение» вы узнаете больше о рабочих состояниях и о том, как отслеживать ход своей работы.

,

В руководстве по началу работы описано, как создать простой WorkRequest и поставить его в очередь.

В этом руководстве вы узнаете, как определять и настраивать объекты WorkRequest для обработки распространенных случаев использования, например, как:

  • Планирование разовых и периодических работ
  • Установите рабочие ограничения, например требование Wi-Fi или зарядки.
  • Гарантируем минимальную задержку выполнения работ
  • Установите стратегии повтора и отсрочки
  • Передайте входные данные на работу
  • Групповая работа работает вместе с использованием тегов

Обзор

Работа определена в Workmanager через WorkRequest . Чтобы запланировать любую работу с Workmanager, вы должны сначала создать объект WorkRequest , а затем включить его.

Котлин

val myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest)

Ява

WorkRequest myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest);

Объект WorkRequest содержит всю информацию, необходимую Workmanager, для планирования и запуска вашей работы. Он включает в себя ограничения, которые должны быть выполнены для вашей работы для выполнения, планирования информации, такой как задержки или повторяющиеся интервалы, повторная конфигурация, и может включать входные данные, если ваша работа полагается на них.

Сам WorkRequest - это абстрактный базовый класс. Существует две выведенные реализации этого класса, которые вы можете использовать для создания запроса, OneTimeWorkRequest и PeriodicWorkRequest . Как подразумевают их имена, OneTimeWorkRequest полезен для планирования не повторных работ, в то время как PeriodicWorkRequest более подходит для планирования работы, которая повторяется в некотором интервале.

Запланируйте единовременную работу

Для простой работы, которая не требует дополнительной конфигурации, используйте статический метод from :

Котлин

val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)

Ява

WorkRequest myWorkRequest = OneTimeWorkRequest.from(MyWork.class);

Для более сложной работы вы можете использовать строитель:

Котлин

val uploadWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       // Additional configuration
       .build()

Ява

WorkRequest uploadWorkRequest =
   new OneTimeWorkRequest.Builder(MyWork.class)
       // Additional configuration
       .build();

Расписание ускоренная работа

Workmanager 2.7.0 представил концепцию ускоренной работы. Это позволяет Workmanager выполнять важную работу, предоставляя системе лучше контролировать доступ к ресурсам.

Ускоренная работа примечательна для следующих характеристик:

  • Важность : Ускоренные рабочие костюмы, которые важны для пользователя или инициированы пользователем.
  • Скорость : ускоренная работа лучше всего подходит для коротких задач, которые начинаются немедленно и завершаются в течение нескольких минут.
  • Квоты : квота на уровне системы, которая ограничивает время выполнения переднего плана, определяет, может ли ускоренная задача начать.
  • Управление питанием : ограничения управления питанием , такие как спасение аккумулятора и доза, с меньшей вероятностью повлияют на ускоренную работу.
  • Задержка : система немедленно выполняет ускоренную работу, при условии, что текущая рабочая нагрузка системы позволяет ей сделать это. Это означает, что они чувствительны к задержке и не могут быть запланированы на последующее выполнение.

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

Квоты

Система должна выделить время выполнения на ускоренную работу, прежде чем она сможет запустить. Время исполнения не ограничено. Скорее, каждое приложение получает квоту времени исполнения. Когда ваше приложение использует время выполнения и достигает своей выделенной квоты, вы больше не можете выполнять ускоренную работу, пока квота не будет обновлена. Это позволяет Android более эффективно сбалансировать ресурсы между приложениями.

Количество времени выполнения, доступное для приложения, основано на резервном ведре и важности процесса.

Вы можете определить, что происходит, когда квота выполнения не допускает ускоренную работу немедленно выполнять. Смотрите фрагменты ниже для деталей.

Выполнение ускоренной работы

Начиная с Workmanager 2.7, ваше приложение может позвонить setExpedited() чтобы заявить, что WorkRequest должен работать как можно быстрее, используя ускоренную работу. В следующем фрагменте кода приведен пример использования setExpedited() :

Котлин

val request = OneTimeWorkRequestBuilder<SyncWorker>()
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build()

WorkManager.getInstance(context)
    .enqueue(request)

Ява

OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>()
    .setInputData(inputData)
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build();

В этом примере мы инициализируем экземпляр OneTimeWorkRequest и вызов setExpedited() . Затем этот запрос становится ускоренной работой. Если квота позволяет, она начнет работать немедленно в фоновом режиме. Если квота была использована, параметр OutOfQuotaPolicy указывает, что запрос должен выполняться как нормальная, неэтагированная работа.

Обратная совместимость и услуги переднего плана

Чтобы поддерживать обратную совместимость для ускоренных заданий, Workmanager может запустить услугу переднего платформы на версиях платформы, старше Android 12. Службы переднего плана могут отобразить уведомление пользователю.

Методы getForegroundInfoAsync() и getForegroundInfo() в вашем работнике позволяют Workmanager отобразить уведомление при вызове setExpedited() до Android 12.

Любой ListenableWorker должен реализовать метод getForegroundInfo если вы хотите запросить, чтобы задача выполнялась в качестве ускоренной работы.

При нацеливании на Android 12 или выше услуги переднего плана остаются доступными для вас через соответствующий метод setForeground .

Рабочий

Рабочие не знают, ускоряется ли работа, которую они выполняют или нет. Но работники могут отображать уведомление о некоторых версиях Android, когда WorkRequest был ускорен.

Чтобы включить это, Workmanager предоставляет метод getForegroundInfoAsync() , который вы должны реализовать, чтобы WorkManager мог отобразить уведомление, чтобы запустить для вас ForegroundService , где это необходимо.

Корешер

Если вы используете CoroutineWorker , вы должны реализовать getForegroundInfo() . Затем вы передаете его setForeground() в doWork() . Это создаст уведомление в версиях Android до 12.

Рассмотрим следующий пример:

  class ExpeditedWorker(appContext: Context, workerParams: WorkerParameters):
   CoroutineWorker(appContext, workerParams) {

   override suspend fun getForegroundInfo(): ForegroundInfo {
       return ForegroundInfo(
           NOTIFICATION_ID, createNotification()
       )
   }

   override suspend fun doWork(): Result {
       TODO()
   }

    private fun createNotification() : Notification {
       TODO()
    }

}

Политика квот

Вы можете контролировать то, что происходит с ускоренной работой, когда ваше приложение достигает своей квоты выполнения. Чтобы продолжить, вы можете передать setExpedited() :

  • OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST , что заставляет задание работать в качестве обычного запроса на работу. Приведенный выше фрагмент демонстрирует это.
  • OutOfQuotaPolicy.DROP_WORK_REQUEST , который приводит к отмене запроса, если нет достаточной квоты.

Пример приложения

Чтобы увидеть полный пример того, как Workmanager 2.7.0 использует ускоренную работу, просмотрите образцовый образцо на GitHub.

Отсроченная ускоренная работа

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

  • Нагрузка : Системная нагрузка слишком высока, что может произойти, когда слишком много заданий уже работает, или когда в системе недостаточно памяти.
  • Квота : Ускоренный лимит квоты работы был превышен. Ускоренная работа использует систему квот, которая основана на ведрах в режиме ожидания приложения и ограничивает максимальное время выполнения в окне проката. Квоты, используемые для ускоренной работы, являются более ограничительными, чем те, которые используются для других типов фоновых заданий.

Расписание периодической работы

Ваше приложение может иногда требовать, чтобы определенные работы периодически работали. Например, вы можете периодически резервное копирование ваших данных, загружать свежий контент в вашем приложении или загружать журналы на сервер.

Вот как вы используете PeriodicWorkRequest для создания объекта WorkRequest , который периодически выполняется:

Котлин

val saveRequest =
       PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)
    // Additional configuration
           .build()

Ява

PeriodicWorkRequest saveRequest =
       new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS)
           // Constraints
           .build();

В этом примере работа запланирована с интервалом на один час.

Интервальный период определяется как минимальное время между повторениями. Точное время, которое будет выполнять работник, зависит от ограничений, которые вы используете в своем объекте WorkRequest и от оптимизации, выполняемых системой.

Гибкие интервалы пробега

Если характер вашей работы делает его чувствительным к временному времени запуска, вы можете настроить свой PeriodicWorkRequest чтобы запустить в течение периода гибкого периода в каждом интервальном периоде, как показано на рисунке 1.

Вы можете установить интервал сгиба для периодической работы. Вы определяете повторный интервал, и интервал сгиба, который определяет определенное количество времени в конце Повторный интервал. Workmanager пытается запустить вашу работу в какой -то момент во время Изгиб интервал в каждом цикле.

На рисунке 1. Диаграмма показывает повторяющиеся интервалы с гибким периодом, когда работа может работать.

Чтобы определить периодическую работу с периодом сгиба, вы передаете flexInterval вместе с repeatInterval при создании PeriodicWorkRequest . Период сгиба начинается в repeatInterval - flexInterval и идет до конца интервала.

Ниже приведен пример периодической работы, которая может работать в течение последних 15 минут каждого часа.

Котлин

val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
       1, TimeUnit.HOURS, // repeatInterval (the period cycle)
       15, TimeUnit.MINUTES) // flexInterval
    .build()

Ява

WorkRequest saveRequest =
       new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class,
               1, TimeUnit.HOURS,
               15, TimeUnit.MINUTES)
           .build();

Интервал повторения должен быть больше или равен PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS

Влияние ограничений на периодическую работу

Вы можете применить ограничения для периодической работы. Например, вы можете добавить ограничение на ваш рабочий запрос, так что работа работает только тогда, когда устройство пользователя заряжается. В этом случае, даже если определенный интервал повторения пройдет, PeriodicWorkRequest не будет работать до тех пор, пока это условие не будет выполнено. Это может привести к отсрочке конкретного прогона вашей работы или даже пропущенного, если условия не выполняются в интервале пробега.

Рабочие ограничения

Ограничения гарантируют, что работа будет отложена до тех пор, пока не будут выполнены оптимальные условия. Следующие ограничения доступны для Workmanager.

NetworkType Ограничивает тип сети, необходимую для выполнения вашей работы. Например, Wi-Fi ( UNMETERED ).
BatteryNotlow При установке в True ваша работа не будет работать, если устройство находится в режиме низкой батареи.
Требуется заряд Когда установлено в True, ваша работа будет работать только тогда, когда устройство заряжается.
DeviceIdle При установке True, это требует, чтобы устройство пользователя было холостое время, прежде чем работа будет выполнена. Это может быть полезно для запуска пакетных операций, которые в противном случае могли бы оказать негативное влияние на производительность на другие приложения, активно работающие на устройстве пользователя.
Storagenotlow Когда установлено в True, ваша работа не будет работать, если место для хранения пользователя на устройстве слишком низкое.

Чтобы создать набор ограничений и связать его с некоторой работой, создайте экземпляр Constraints используя Contraints.Builder() и назначьте его на свой WorkRequest.Builder() .

Например, следующий код создает рабочий запрос, который работает только тогда, когда устройство пользователя заряжается и на Wi-Fi:

Котлин

val constraints = Constraints.Builder()
   .setRequiredNetworkType(NetworkType.UNMETERED)
   .setRequiresCharging(true)
   .build()

val myWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       .setConstraints(constraints)
       .build()

Ява

Constraints constraints = new Constraints.Builder()
       .setRequiredNetworkType(NetworkType.UNMETERED)
       .setRequiresCharging(true)
       .build();

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
               .setConstraints(constraints)
               .build();

Когда будут указаны несколько ограничений, ваша работа будет работать только тогда, когда все ограничения будут выполнены.

В случае, если ограничение становится неудовлетворенным во время работы вашей работы, Workmanager остановит вашего работника. Работа будет затем повторно, когда все ограничения будут выполнены.

Задержка работы

В случае, если ваша работа не имеет ограничений или что все ограничения выполняются, когда ваша работа будет включена, система может сразу запустить работу. Если вы не хотите, чтобы работа была запускана немедленно, вы можете указать свою работу, чтобы начать после минимальной начальной задержки.

Вот пример того, как установить свою работу, чтобы запустить не менее 10 минут после того, как она была включена.

Котлин

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setInitialDelay(10, TimeUnit.MINUTES)
   .build()

Ява

WorkRequest myWorkRequest =
      new OneTimeWorkRequest.Builder(MyWork.class)
               .setInitialDelay(10, TimeUnit.MINUTES)
               .build();

В то время как пример иллюстрирует, как установить начальную задержку для OneTimeWorkRequest , вы также можете установить начальную задержку для PeriodicWorkRequest . В этом случае только первый пробег вашей периодической работы будет отложено.

Политика повторной попытки

Если вам требуется, чтобы Workmanager повторно выполнил вашу работу, вы можете вернуть Result.retry() от своего работника. Затем ваша работа перенесена в соответствии с политикой задержки и отключения отбора .

  • Задержка отступления указывает минимальное количество времени, чтобы подождать, прежде чем повторить вашу работу после первой попытки. Это значение может быть не менее 10 секунд (или min_backoff_millis ).

  • Политика отступления определяет, как задержка отступления должна увеличиваться с течением времени для последующих попыток повторения. Workmanager поддерживает 2 политики отдачи, LINEAR и EXPONENTIAL .

Каждый запрос на работу имеет политику отключения и задержку отключения. Политика по умолчанию является EXPONENTIAL с задержкой на 30 секунд, но вы можете переопределить это в конфигурации вашего рабочего запроса.

Вот пример настройки задержки и политики отбора.

Котлин

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setBackoffCriteria(
       BackoffPolicy.LINEAR,
       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
       TimeUnit.MILLISECONDS)
   .build()

Ява

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
               .setBackoffCriteria(
                       BackoffPolicy.LINEAR,
                       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                       TimeUnit.MILLISECONDS)
               .build();

В этом примере минимальная задержка отступления устанавливается на минимальное допустимое значение, 10 секунд. Поскольку политика является LINEAR интервал повторения увеличится примерно на 10 секунд с каждой новой попыткой. Например, первый пробег заканчивается с Result.retry() снова будет предпринят через 10 секунд, а затем 20, 30, 40 и т. Д., Если работа продолжает возвращать Result.retry() после последующих попыток. Если бы политика отступления была установлена ​​на EXPONENTIAL , последовательность продолжительности повторения была бы ближе к 20, 40, 80 и т. Д.

Тег работ

Каждый запрос на работу имеет уникальный идентификатор , который можно использовать для определения этой работы позже, чтобы отменить работу или наблюдать за ее прогрессом .

Если у вас есть группа логически связанной работы, вам также может быть полезным пометить эти рабочие элементы. Тегинг позволяет вам работать вместе с группой рабочих запросов вместе.

Например, WorkManager.cancelAllWorkByTag(String) отменяет все рабочие запросы с помощью конкретного тега, а WorkManager.getWorkInfosByTag(String) возвращает список объектов WorkInfo, которые можно использовать для определения текущего рабочего состояния.

Следующий код показывает, как вы можете добавить тег «очистки» в свою работу:

Котлин

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .addTag("cleanup")
   .build()

Ява

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
       .addTag("cleanup")
       .build();

Наконец, несколько тегов могут быть добавлены в один запрос на работу. Внутренне эти теги хранятся как набор струн. Чтобы получить набор тегов, связанных с WorkRequest вы можете использовать workinfo.gettags () .

Из вашего класса Worker вы можете получить его набор тегов с помощью слушателей .

Назначьте входные данные

Ваша работа может потребовать входных данных для выполнения своей работы. Например, работа, которая обрабатывает загрузку изображения, может потребовать загрузки URI изображения в качестве входного.

Входные значения хранятся как пары клавиш в объекте Data и могут быть установлены в рабочем запросе. Workmanager предоставит входные Data в вашу работу, когда выполняет работу. Класс Worker может получить доступ к входным аргументам, позвонив в Worker.getInputData() . Приведенный ниже код показывает, как вы можете создать экземпляр Worker , который требует входных данных и как отправить его в ваш рабочий запрос.

Котлин

// Define the Worker requiring input
class UploadWork(appContext: Context, workerParams: WorkerParameters)
   : Worker(appContext, workerParams) {

   override fun doWork(): Result {
       val imageUriInput =
           inputData.getString("IMAGE_URI") ?: return Result.failure()

       uploadFile(imageUriInput)
       return Result.success()
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>()
   .setInputData(workDataOf(
       "IMAGE_URI" to "http://..."
   ))
   .build()

Ява

// Define the Worker requiring input
public class UploadWork extends Worker {

   public UploadWork(Context appContext, WorkerParameters workerParams) {
       super(appContext, workerParams);
   }

   @NonNull
   @Override
   public Result doWork() {
       String imageUriInput = getInputData().getString("IMAGE_URI");
       if(imageUriInput == null) {
           return Result.failure();
       }

       uploadFile(imageUriInput);
       return Result.success();
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
WorkRequest myUploadWork =
      new OneTimeWorkRequest.Builder(UploadWork.class)
           .setInputData(
               new Data.Builder()
                   .putString("IMAGE_URI", "http://...")
                   .build()
           )
           .build();

Аналогичным образом, класс Data может использоваться для вывода возвращаемого значения. Входные и выходные данные более подробно рассмотрены в параметрах ввода раздела и возвращенных значениях .

Следующие шаги

На странице государств и наблюдения вы узнаете больше о состояниях работы и о том, как контролировать прогресс вашей работы.