WorkManager — це Jetpack-бібліотека Android, призначена для виконання відкладених і фонових завдань з гарантією виконання. На відміну від Service або JobScheduler, WorkManager бере на себе управління життєвим циклом завдання: перезапускає його при збої, адаптується до версії Android та враховує обмеження пристрою. За даними Android Developers, 2026, WorkManager є кращим рішенням для більшості фонових операцій у сучасній Android-розробці.
Головне
WorkManager — це частина Android Jetpack, бібліотека для управління фоновими завданнями, які повинні виконатися гарантовано, незалежно від того, чи знаходиться додаток на передньому плані або був закритий користувачем. Бібліотека підтримує API 14+ і автоматично вибирає відповідний механізм виконання: JobScheduler на Android 5+, BroadcastReceiver + AlarmManager на більш старих версіях.
Ключова особливість WorkManager — гарантія виконання. Якщо завдання не було завершено через перезавантаження пристрою, зупинку додатка або збій, WorkManager перезапустить його при першій можливості. Це робить бібліотеку ідеальним вибором для завдань, критичних до виконання: відправка аналітики, синхронізація бази даних, завантаження логів.
На відміну від Background Service, WorkManager не вимагає управління потоками та життєвим циклом. Бібліотека сама створює пул потоків, обробляє Doze Mode, враховує версію Android і надає єдиний API незалежно від рівня API. Робота з корутинами та RxJava підтримується через CoroutineWorker та RxWorker відповідно.
WorkManager надає вбудовану підтримку LiveData для відстеження стану завдань. Метод getWorkInfoByIdLiveData повертає LiveData<WorkInfo>, яка оновлюється при кожній зміні стану: ENQUEUED, RUNNING, SUCCEEDED, FAILED, CANCELLED. Це дозволяє UI-компонентам реагувати на зміни без ручного опитування планувальника та без витоків пам'яті завдяки Lifecycle-aware компонентам.
WorkManager.getInstance(context)
.getWorkInfoByIdLiveData(syncRequest.id)
.observe(viewLifecycleOwner) { workInfo ->
when (workInfo.state) {
WorkInfo.State.SUCCEEDED ->
showSuccess()
WorkInfo.State.FAILED ->
showError(workInfo.outputData)
else ->
showProgress()
}
}
Архітектура WorkManager будується навколо трьох базових класів: Worker, WorkRequest і WorkManager. Worker містить логіку завдання, WorkRequest описує параметри виконання, а WorkManager управляє чергою та плануванням. Бібліотека використовує внутрішню базу даних Room для зберігання стану всіх завдань.
Worker — це абстрактний клас з єдиним методом doWork, який викликається у фоновому потоці. Метод повертає ListenableWorker.Result — SUCCESS, FAILURE або RETRY. WorkRequest пов'язує Worker з параметрами: тайм-аутом, тегом, початковою затримкою та обмеженнями.
class SyncWorker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
override fun doWork(): Result {
return try {
val api = RetrofitClient.api
val response = api.syncData()
Result.success()
} catch (e: Exception) {
Result.retry()
}
}
}
WorkManager єдинообразно планує завдання незалежно від версії Android. При виклику enqueue бібліотека зберігає завдання в Room, оцінює поточні умови та вибирає оптимальний час запуску. Під капотом може використовуватися JobScheduler, AlarmManager або власний планувальник — розробник про це не замислюється.
val syncRequest = OneTimeWorkRequestBuilder<SyncWorker>()
.setInitialDelay(15, TimeUnit.MINUTES)
.addTag("sync")
.build()
WorkManager.getInstance(context)
.enqueue(syncRequest)
WorkManager підтримує два типи запитів на виконання: одноразові та періодичні. Вибір типу залежить від сценарію: завдання повинно виконатися один раз або повторюватися через заданий інтервал.
OneTimeWorkRequest призначений для завдань, які повинні виконатися одноразово. Це може бути відправка лога, синхронізація даних після авторизації, завантаження конфігурації при першому запуску. Затримка задається через setInitialDelay, а обмеження — через setConstraints.
PeriodicWorkRequest підходить для повторюваних завдань з мінімальним інтервалом 15 хвилин. Бібліотека гарантує, що інтервал між запусками не буде менше вказаного, але може бути більшим через обмеження пристрою. Для завдань з частотою менше 15 хвилин використовуйте Handler або Timer в Foreground Service.
| Параметр | OneTimeWorkRequest | PeriodicWorkRequest |
|---|---|---|
| Частота | одноразово | повторно (мін. 15 хв) |
| Кількість | 1 виконання | до скасування |
| Затримка | setInitialDelay | setInitialDelay |
| Ланцюжки | підтримує | ні |
| Використання | завантаження, синхронізація | моніторинг, пуллінг |
Обмеження в WorkManager дозволяють задати умови, при яких завдання може бути запущено: підключення до мережі (NetworkType), рівень заряду батареї (batteryNotLow), стан сховища (StorageNotLow) і режим очікування (DeviceIdle). Завдання не запуститься, поки всі обмеження не будуть виконані.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresCharging(true)
.setRequiresBatteryNotLow(true)
.build()
val request = OneTimeWorkRequestBuilder<ImageUploadWorker>()
.setConstraints(constraints)
.build()
Ланцюжки дозволяють організувати послідовне або паралельне виконання завдань. beginWith запускає ланцюжок, then додає наступний Worker, який виконається після успішного завершення попереднього. Для паралельного виконання використовується workManager.enqueue(listOf(request1, request2)).
WorkManager.getInstance(context)
.beginWith(compressWorker)
.then(uploadWorker)
.then(cleanupWorker)
.enqueue()
// compress -> upload -> cleanup послідовно
JobScheduler був введений в Android 5 (API 21) як системний сервіс для планування фонових завдань. WorkManager прийшов на зміну, запропонувавши крос-платформений API з автоматичною міграцією та додатковими можливостями: ланцюжки, гарантія виконання, теги, спостереження за станом через LiveData.
При міграції з JobScheduler на WorkManager потрібно перетворити JobService на Worker, замінити JobInfo на WorkRequest, а Context.getSystemService на WorkManager API. WorkManager автоматично вирішує проблеми сумісності та обробляє Doze Mode коректніше, ніж ручна імплементація JobScheduler. Кроки міграції: 1) створити Worker-клас, 2) побудувати WorkRequest з тими ж умовами, 3) видалити JobService та JobInfo з коду та маніфесту.
WorkManager підтримує концепцію унікальних завдань через ExistingWorkPolicy. Якщо завдання з вказаним ім'ям вже існує, політика визначає поведінку: KEEP (не створювати нове), REPLACE (замінити існуюче), APPEND (додати в кінець ланцюжка) та APPEND_OR_REPLACE. UniqueWorkRequest зручний для завдань, які не повинні дублюватися: синхронізація бази даних, завантаження конфігурації, відправка пакета аналітики.
WorkManager.getInstance(context)
.enqueueUniqueWork(
"sync_data",
ExistingWorkPolicy.KEEP,
syncRequest
)
CoroutineWorker підтримує механізм setProgress, що дозволяє передавати проміжні результати виконання завдання. Це корисно для тривалих операцій: завантаження великого файлу, пакетна обробка зображень, міграція бази даних. UI може підписатися на оновлення через getWorkInfosByTagLiveData та відображати прогрес у реальному часі. Доступний також метод ForegroundInfo для запуску Worker як Foreground Service з повідомленням, якщо завдання повинно бути видимим користувачеві.
class ProgressWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val total = 100
for (i in 1..total) {
setProgress(
workDataOf("progress" to i)
)
}
return Result.success()
}
}
WorkManager підтримує передачу даних між Worker-ами через InputData та OutputData. InputData створюється на етапі побудови WorkRequest через Data.Builder і передається в Worker через inputData. Після виконання Worker формує OutputData через workDataOf або Data.Builder і повертає разом з Result.success(outputData). Наступний Worker в ланцюжку отримує outputData попереднього як свій inputData. Дані зберігаються у форматі ключ-значення з підтримкою базових типів: String, Int, Long, Boolean, Double. Максимальний розмір Data — 10 КБ.
На практиці багато проектів використовують WorkManager як єдиний планувальник фонових завдань. Google рекомендує мігрувати всі існуючі JobService на WorkManager, особливо в додатках, що підтримують Android 4.4 (API 19) і нижче, де JobScheduler недоступний, а WorkManager використовує резервний механізм через AlarmManager та BroadcastReceiver. Для тестування WorkManager надає TestListenableWorkerBuilder та TestWorkerBuilder, які дозволяють тестувати Worker-ів у JUnit-тестах без реального планувальника.
Для тестування WorkManager використовуйте TestListenableWorkerBuilder з AndroidX Test, який дозволяє запускати Worker в ізольованому середовищі та перевіряти повернутий Result. Бібліотека надає повну підтримку JUnit та Robolectric для модульного тестування без реального планувальника. Загалом WorkManager підходить для 80% завдань, де раніше використовувалися Service або JobScheduler.
Часті запитання
Так, WorkManager гарантує виконання навіть після перезавантаження. Бібліотека зберігає всі незавершені завдання в Room-базу даних та відновлює їх за допомогою BroadcastReceiver, який спрацьовує після завантаження системи.
Worker працює у фоновому потоці без підтримки корутин або RxJava. CoroutineWorker використовує Kotlin-корутини з підтримкою suspend-функцій та відміни за корутинним scope. RxWorker працює з Observable та Single, підходить для реактивних ланцюжків.
Для скасування використовуйте workManager.cancelWorkById(id) або workManager.cancelAllWorkByTag("tag"). Бібліотека також надає метод cancelUniqueWork("name") для скасування унікальних завдань з вказаним ім'ям.
Мінімальний інтервал для PeriodicWorkRequest становить 15 хвилин. Це обмеження встановлено Google для запобігання надмірному витрачанню батареї. Якщо завдання повинно виконуватися частіше, використовуйте Foreground Service або Handler з таймером.
Так, WorkManager підтримує API 14+. На пристроях без JobScheduler (нижче API 21) бібліотека використовує комбінацію AlarmManager та BroadcastReceiver для планування завдань. Це робить WorkManager універсальним рішенням для фонових завдань.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також