← Назад к вопросам
Как реализовать фоновую работу с WorkManager?
2.0 Middle🔥 231 комментариев
#Многопоточность и асинхронность
Комментарии (1)
🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Реализация фоновой работы с WorkManager
WorkManager — это современный API для гарантированного выполнения отложенных фоновых задач, который учитывает версию Android и состояние системы. Он совмещает преимущества JobScheduler, Firebase JobDispatcher и AlarmManager, предоставляя единый интерфейс.
Основные концепции
- Worker — класс, содержащий логику фоновой работы
- WorkRequest — запрос на выполнение работы (разовый или периодический)
- WorkInfo — информация о состоянии и результатах работы
- Constraints — ограничения для выполнения (сеть, зарядка и т.д.)
- WorkManager — менеджер, который ставит работу в очередь и управляет выполнением
Шаги реализации
1. Добавление зависимостей
// build.gradle (module)
dependencies {
implementation "androidx.work:work-runtime-ktx:2.9.0"
// Для многопроцессорной работы (опционально)
implementation "androidx.work:work-multiprocess:2.9.0"
}
2. Создание Worker класса
class MyWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
// Выполняем фоновую работу
val data = downloadData()
processData(data)
// Возвращаем результат
Result.success(
workDataOf(
"result_key" to "Данные успешно обработаны",
"processed_items" to data.size
)
)
} catch (e: Exception) {
// При ошибке можно повторить попытку
if (runAttemptCount < 3) {
Result.retry()
} else {
Result.failure(
workDataOf("error" to e.message)
)
}
}
}
private suspend fun downloadData(): List<String> {
delay(5000) // Имитация долгой операции
return listOf("item1", "item2", "item3")
}
private fun processData(data: List<String>) {
// Логика обработки данных
}
}
3. Создание WorkRequest
Разовый запрос:
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresCharging(true)
.setRequiresBatteryNotLow(true)
.build()
val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(constraints)
.setInitialDelay(10, TimeUnit.MINUTES) // Задержка перед выполнением
.setBackoffCriteria(
BackoffPolicy.LINEAR,
OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS
)
.setInputData(
workDataOf(
"url" to "https://api.example.com/data",
"priority" to "high"
)
)
.addTag("sync_tag")
.build()
Периодический запрос:
val periodicWorkRequest = PeriodicWorkRequestBuilder<MyWorker>(
15, TimeUnit.MINUTES, // Интервал повторения
5, TimeUnit.MINUTES // Гибкое окно выполнения
).build()
4. Запуск и управление работой
class MainActivity : AppCompatActivity() {
private lateinit var workManager: WorkManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
workManager = WorkManager.getInstance(this)
// Запуск работы
val workRequest = createWorkRequest()
workManager.enqueue(workRequest)
// Отслеживание состояния
workManager.getWorkInfoByIdLiveData(workRequest.id)
.observe(this) { workInfo ->
when (workInfo?.state) {
WorkInfo.State.ENQUEUED -> Log.d("WorkManager", "В очереди")
WorkInfo.State.RUNNING -> Log.d("WorkManager", "Выполняется")
WorkInfo.State.SUCCEEDED -> {
val result = workInfo.outputData.getString("result_key")
Log.d("WorkManager", "Успешно: $result")
}
WorkInfo.State.FAILED -> Log.d("WorkManager", "Ошибка")
WorkInfo.State.BLOCKED -> Log.d("WorkManager", "Заблокировано")
WorkInfo.State.CANCELLED -> Log.d("WorkManager", "Отменено")
}
}
}
// Отмена работы
fun cancelWork() {
workManager.cancelWorkById(workRequest.id)
// Или по тегу
workManager.cancelAllWorkByTag("sync_tag")
}
// Отмена всей работы
fun cancelAllWork() {
workManager.cancelAllWork()
}
}
Продвинутые техники
Цепочки работ (Work Chains)
val compressWork = OneTimeWorkRequestBuilder<CompressWorker>()
.build()
val uploadWork = OneTimeWorkRequestBuilder<UploadWorker>()
.build()
val downloadWork = OneTimeWorkRequestBuilder<DownloadWorker>()
.build()
// Параллельное выполнение compressWork и uploadWork,
// затем последовательное выполнение downloadWork
workManager.beginWith(listOf(compressWork, uploadWork))
.then(downloadWork)
.enqueue()
Уникальные последовательности
// Гарантирует, что только одна работа с таким именем будет выполняться
workManager.beginUniqueWork(
"unique_work_name",
ExistingWorkPolicy.REPLACE, // или KEEP, APPEND
workRequest
).enqueue()
Лучшие практики
- Используйте CoroutineWorker для асинхронных операций вместо Thread/RxJava
- Всегда накладывайте Constraints для оптимизации батареи
- Обрабатывайте прерывания через
isStoppedвWorker - Логируйте состояние через
setProgress()для длительных операций - Используйте теги для группировки и управления работами
- Тестируйте с помощью
WorkManagerTestInitHelper
Особенности на разных версиях Android
- API 23+: Используется JobScheduler
- API 14-22: Используется комбинация AlarmManager + BroadcastReceiver
- Всегда гарантируется выполнение даже после перезагрузки устройства
WorkManager интегрирован с Architecture Components и поддерживает жизненный цикл приложения, автоматически останавливая работы при завершении приложения и возобновляя при необходимости.