WorkManager: очередь задач, которая переживает экран, но не обещает точный час
Ограничения запуска, уникальные задания, цепочки, прогресс и квоты длительной работы в Android.

Запись о работе важнее живого экрана
WorkManager предназначен для задач, которым нужно продолжаться после ухода приложения с видимого экрана. Он сохраняет описание запланированной работы и восстанавливает расписание после перезапуска приложения или устройства. Это отличается от coroutine, чья жизнь непосредственно связана с текущим экраном или процессом.
Устойчивая запись о задаче не означает непрерывного выполнения одного и того же потока. Система может остановить выполнение и позже запустить работу в допустимых условиях. WorkManager хранит расписание во внутренней SQLite-базе и согласует его с энергосберегающими механизмами Android. Поэтому формулировка «переживает перезагрузку» относится к плану выполнения, а не к сохранению оперативной памяти Worker. Три описываемые группы — немедленная короткая, длительная и отложенная работа — имеют разные требования к запуску и представлению пользователю. Они используют общую библиотеку, но не получают одинаковые системные привилегии только из-за общего имени API.
Ограничения проверяются совместно
WorkRequest содержит условия запуска, расписание, политику повторов и входные данные. Можно потребовать подходящую сеть, зарядку, достаточный заряд, свободное место либо простой устройства. Если указано несколько условий, они должны выполняться одновременно.
Утрата условия во время выполнения может остановить Worker; позднее работа повторяется при восстановлении подходящих условий. Например, наличие сети при постановке задания не гарантирует её сохранения до окончания загрузки. Требование UNMETERED описывает характеристику тарификации соединения, а не универсальный синоним любой Wi-Fi-сети. Сам запрос работы описывает допустимые условия, но не является соединением с сервером и не подтверждает, что удалённый ресурс уже доступен.
Интервал не превращается в будильник
OneTimeWorkRequest описывает непериодическую работу, PeriodicWorkRequest — повторяющуюся. Минимальный период составляет пятнадцать минут. Фактический момент зависит от ограничений и оптимизаций системы, поэтому период не гарантирует запуск в конкретную секунду.
Flex задаёт допустимую часть в конце очередного интервала. Ограничение зарядки способно отложить или пропустить выполнение в данном окне. Начальная задержка устанавливает нижнюю границу ожидания, а не точный срок. Expedited work также ограничена квотой и загрузкой системы; при её исчерпании политика определяет перевод в обычную работу либо отмену. Такой запрос важнее обычного планового задания, но не отменяет управление ресурсами Android.

Уникальное имя защищает очередь от дубликатов
Каждый запрос имеет собственный идентификатор. Unique work добавляет содержательное имя, по которому WorkManager разрешает конфликт с уже существующей незавершённой работой. Это полезно, когда один и тот же экран или обработчик способен повторно поставить задачу. Тег, напротив, группирует запросы и не делает их единственным экземпляром.
Для одноразовой работы KEEP сохраняет существующую цепочку, REPLACE отменяет её и ставит новую, APPEND добавляет продолжение. APPEND_OR_REPLACE отдельно обрабатывает цепочки, предшественники которых уже завершились ошибкой или были отменены. Это политика очереди, а не гарантия единственного изменения на удалённом сервере. Если сетевой запрос достиг сервера, а локальная работа была остановлена до фиксации результата, повторная попытка остаётся возможной. Уникальное локальное имя и серверная защита от повторного выполнения описывают разные границы операции. Таблица ниже сравнивает именно поведение незавершённых цепочек, не выдавая его за распределённую транзакцию.
| Политика | При существующей незавершённой цепочке |
|---|---|
| KEEP | Сохранить существующую |
| REPLACE | Отменить и заменить новой |
| APPEND | Добавить зависимое продолжение |
| APPEND_OR_REPLACE | Добавить; заменить при ошибочных или отменённых предшественниках |
Источник: Android: ExistingWorkPolicy
Цепочка выражает зависимости
beginWith создаёт начало последовательности, then добавляет зависимые этапы. Список запросов на одном уровне может выполняться параллельно. Следующий этап ожидает успешного завершения необходимых предшественников, а не просто истечения времени после их запуска. Это позволяет, например, сначала независимо обработать несколько входных объектов, затем объединить результаты и только после этого отправить общий набор.
Выходные Data предшественников становятся входом потомка. При совпадении ключей OverwritingInputMerger оставляет одно значение, тогда как ArrayCreatingInputMerger собирает значения в массив. Для параллельных этапов порядок завершения не гарантирован, поэтому одинаковый ключ с разными значениями нельзя считать устойчиво определённым выбором. Ошибка или отмена предшественника влияет на зависимые узлы; повтор отдельного этапа не обязан перезапускать независимую параллельную ветку. Цепочка описывает граф зависимостей, но не делает все этапы одной неделимой операцией с автоматическим откатом внешних изменений.

Прогресс хранится как данные
Worker может публиковать промежуточный прогресс через Data. Для ListenableWorker используется setProgressAsync, для CoroutineWorker доступен suspending setProgress. Обновление сохраняется асинхронно, а интерфейс наблюдает его через WorkInfo и соответствующие методы получения состояния. Поэтому прогресс не обязан храниться в переменной прежней Activity.
Эти значения имеют смысл во время выполнения. Попытка задать прогресс уже завершившемуся Worker игнорируется. Процент также не является автоматически измеренной системной величиной: приложение определяет, что именно означает сообщённое число. Оно может отражать количество обработанных записей, завершённые этапы или иную честно заданную меру. Наличие промежуточного значения не заменяет финального Result. Статус успеха, ошибки или повторной попытки передаётся отдельно. Экран способен исчезнуть и появиться снова, но наблюдение за работой остаётся привязано к её идентификатору и сохранённым сведениям, а не к непрерывному существованию одного визуального индикатора.
После возвращения на экран приложение запрашивает WorkInfo по известному идентификатору или наблюдает изменения через поддерживаемые представления состояния. Это позволяет отделить выполнение задания от отображения его хода: подписка интерфейса сама по себе не запускает новый экземпляр работы.
Длительная работа не выходит из-под квот
Для длительных Worker библиотека может использовать foreground service и показывать уведомление. ListenableWorker сообщает foreground-состояние через setForegroundAsync, CoroutineWorker — через setForeground. Такой режим позволяет описывать значимую длительную операцию, но не является универсальным обходом ограничений фоновой работы.
Документация отдельно отмечает изменение Android16: long-running workers, использующие foreground services, способны исчерпать квоту заданий приложения, поскольку WorkManager продолжает опираться на JobScheduler. Для некоторых сценариев рассматривается собственная foreground service, а для передачи данных по действию пользователя — user-initiated data transfer job с другими условиями. Следовательно, длинная операция требует выбора подходящего платформенного механизма, а не только увеличения таймера внутри Worker. Уведомление может содержать действие отмены через PendingIntent WorkManager. Отмена сообщает о прекращении локальной работы; смысл уже отправленных данных и необходимость их согласования определяются протоколом приложения, поскольку библиотека не знает, какие внешние последствия успели возникнуть.


