← Назад к вопросам

Как реализовать фоновую работу с WorkManager?

2.0 Middle🔥 231 комментариев
#Многопоточность и асинхронность

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Реализация фоновой работы с WorkManager

WorkManager — это современный API для гарантированного выполнения отложенных фоновых задач, который учитывает версию Android и состояние системы. Он совмещает преимущества JobScheduler, Firebase JobDispatcher и AlarmManager, предоставляя единый интерфейс.

Основные концепции

  1. Worker — класс, содержащий логику фоновой работы
  2. WorkRequest — запрос на выполнение работы (разовый или периодический)
  3. WorkInfo — информация о состоянии и результатах работы
  4. Constraints — ограничения для выполнения (сеть, зарядка и т.д.)
  5. 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()

Лучшие практики

  1. Используйте CoroutineWorker для асинхронных операций вместо Thread/RxJava
  2. Всегда накладывайте Constraints для оптимизации батареи
  3. Обрабатывайте прерывания через isStopped в Worker
  4. Логируйте состояние через setProgress() для длительных операций
  5. Используйте теги для группировки и управления работами
  6. Тестируйте с помощью WorkManagerTestInitHelper

Особенности на разных версиях Android

  • API 23+: Используется JobScheduler
  • API 14-22: Используется комбинация AlarmManager + BroadcastReceiver
  • Всегда гарантируется выполнение даже после перезагрузки устройства

WorkManager интегрирован с Architecture Components и поддерживает жизненный цикл приложения, автоматически останавливая работы при завершении приложения и возобновляя при необходимости.