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

Какие знаешь виды Job?

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

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

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

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

Какие знаешь виды Job?

Этот вопрос может быть о Job в корутинах ИЛИ о Job Scheduling в Android. Отвечу на оба.

Часть 1: Job в Kotlin Coroutines

Job — это дескриптор для управления корутиной. Есть несколько типов по способу управления.

// 1. Из launch
val job1 = launch {
    delay(1000)
    println("Done")
}
job1.join()  // Ждём
job1.cancel()  // Отменяем

// 2. Из async
val job2 = async {
    delay(1000)
    "Result"
}
val result = job2.await()  // Получаем результат

// 3. Job() конструктор
val job3 = Job()
job3.cancel()  // Отменить
job3.complete()  // Завершить вручную

Виды Job:

  1. Обычный Job — привычный дескриптор
val job = Job()
launch(job) {
    // Корутина
}
job.cancel()  // Отменяет корутину
  1. SupervisorJob — при ошибке дочерней корутины родитель не падает
val supervisor = SupervisorJob()
launch(supervisor) {
    launch { throw Exception() }  // Не повалит родителя
    launch { println("Still running") }  // Выполнится
}
  1. Deferred — это Job с результатом
val deferred = async { 42 }
val result = deferred.await()  // Получить результат

Часть 2: Job Scheduling в Android

JobScheduler и WorkManager — это различные виды фоновых работ.

1. Foreground Job (работает сразу)

val job = OneTimeWorkRequestBuilder<MyWorker>()
    .setInitialDelay(0, TimeUnit.SECONDS)
    .build()

WorkManager.getInstance(context).enqueueUniqueWork(
    "foreground",
    ExistingWorkPolicy.KEEP,
    job
)

Характеристики:

  • Запускается сразу
  • Не гарантирует выполнение
  • Может быть убита системой

2. Background Job (фоновая работа)

val job = OneTimeWorkRequestBuilder<MyWorker>()
    .setConstraints(
        Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()
    )
    .build()

WorkManager.getInstance(context).enqueueUniqueWork(
    "background",
    ExistingWorkPolicy.KEEP,
    job
)

Характеристики:

  • Работает в фоне
  • Гарантирует выполнение (даже после перезагрузки)
  • Уважает батарею
  • Требует соблюдение Constraints

3. Exact Job (точное время)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    val jobScheduler = context.getSystemService(JobScheduler::class.java)
    jobScheduler.schedule(
        JobInfo.Builder(1, ComponentName(context, MyJobService::class.java))
            .setPersisted(true)
            .setRequiresDeviceIdle(false)
            .setPeriodic(15 * 60 * 1000)  // Каждые 15 минут
            .build()
    )
}

Характеристики:

  • Точное расписание
  • Требует SCHEDULE_EXACT_ALARM (Android 12+)
  • Может быть отложен системой

4. Periodic Job (повторяющаяся работа)

val periodicJob = PeriodicWorkRequestBuilder<MyWorker>(
    15,  // Интервал
    TimeUnit.MINUTES
).build()

WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "periodic_sync",
    ExistingPeriodicWorkPolicy.KEEP,
    periodicJob
)

Характеристики:

  • Выполняется каждые N минут
  • Гарантирует выполнение
  • Минимум 15 минут между запусками
  • Батарея-friendly

5. Expedited Job (срочная фоновая работа)

val expedited = OneTimeWorkRequestBuilder<MyWorker>()
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED)
    .build()

WorkManager.getInstance(context).enqueueUniqueWork(
    "expedited",
    ExistingWorkPolicy.KEEP,
    expedited
)

Характеристики:

  • Срочное выполнение (лучше чем обычное)
  • Android 12+ имеет квоту
  • Если квота закончилась, работает как обычная

Таблица: типы работ

ТипВремя запускаГарантияБатареяИспользуй
ForegroundСразуНетНетUI работы, быстрое
BackgroundДождьтесь условияДаДаСинхронизация, аналитика
PeriodicКаждый N минутДаДаПериодическая синхронизация
ExpeditedОчень скороЧастичнаяНетВажные фоновые работы
ExactВ точное времяНетНетТаймер, напоминание (требует пермишн)

WorkManager Constraints

val constraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresCharging(true)  // Только во время зарядки
    .setRequiresDeviceIdle(true)  // Только когда телефон не используется
    .setRequiresBatteryNotLow(true)  // Только если батарея не низкая
    .build()

val job = OneTimeWorkRequestBuilder<MyWorker>()
    .setConstraints(constraints)
    .build()

JobService (низкоуровневый API)

class MyJobService : JobService() {
    override fun onStartJob(params: JobParameters?): Boolean {
        // Выполнить работу в фоновом потоке
        doWork()
        return true  // true = работа еще выполняется
    }
    
    override fun onStopJob(params: JobParameters?): Boolean {
        // Работа была прервана
        return true  // true = перезапустить
    }
}

// Регистрация в манифесте
<service
    android:name=".MyJobService"
    android:permission="android.permission.BIND_JOB_SERVICE" />

Выбор между методами

Нужна работа сейчас?
  ↓
  YES: startService() или launch { }
  NO: WorkManager
      ↓
      Периодическая?
        ↓
        YES: PeriodicWorkRequest
        NO: OneTimeWorkRequest
      ↓
      Важна гарантия?
        ↓
        YES: Background constraints
        NO: Expedited

Итог

В Coroutines:

  • Job = дескриптор для управления
  • SupervisorJob = не падает при ошибке дочерней
  • Deferred = Job с результатом

В Android Scheduling:

  • WorkManager = основной современный способ
  • PeriodicWork = повторяющаяся работа
  • JobScheduler = низкоуровневый API (редко нужен)
  • StartService = для видимых работ
  • Constraints = условия выполнения (батарея, сеть и т.д.)