Урок по треку Android 8 мин

Многопоточность и WorkManager за 8 минут

Главный поток и ANR, Dispatchers, сервисы, foreground service и WorkManager.

Android жёстко ограничивает работу в фоне ради батареи. На собесе проверяют, понимаете ли вы главный поток и ANR, корутины в Android, сервисы и их ограничения, и когда брать WorkManager.

Главный поток и ANR

Главный (UI) поток обрабатывает ввод, рисует кадры и вызывает колбэки жизненного цикла. Кадр при 60 Гц должен уложиться в 16 мс, при 120 Гц в 8 мс. Долгая работа на главном потоке даёт рывки (jank), а если приложение не отвечает на ввод 5 секунд, система показывает диалог ANR (Application Not Responding). Для BroadcastReceiver.onReceive лимит около 10 секунд в foreground.

Нельзя на главном потоке: сеть (будет NetworkOnMainThreadException), диск, база, тяжёлые вычисления, декодирование больших картинок.

Под капотом главный поток это Looper с MessageQueue: Handler.post кладёт задачу в очередь, Dispatchers.Main в корутинах работает поверх него.

Корутины в Android

  • viewModelScope для работы экрана, lifecycleScope для UI-задач Activity/Fragment.
  • Dispatchers.IO для блокирующего ввода-вывода, Default для вычислений. Suspend-функции репозиториев main-safe: сами переключают диспетчер через withContext.
  • Корутина в viewModelScope отменится при закрытии экрана. Работа, которая должна завершиться независимо от экрана (отправка сообщения, синхронизация), нужна в другом месте: в application-scope (если процесс жив) или в WorkManager (если должна пережить смерть процесса).

Устаревшие подходы, которые встречаются в легаси: AsyncTask (deprecated, утечки и проблемы при повороте), голые Thread, Executor + Handler, RxJava (живёт во многих проектах).

Сервисы

Service это компонент без UI. Виды:

  • Started service: запущен startService, работает до stopSelf. С Android 8 (API 26) фоновые started-сервисы ограничены: приложение в фоне не может их запускать (IllegalStateException).
  • Foreground service: показывает постоянное уведомление, пользователь знает о работе. Запуск startForegroundService и обязательный вызов startForeground в течение нескольких секунд. С Android 14 (API 34) обязателен тип foreground-сервиса (dataSync, mediaPlayback, location, camera, shortService и др.) в манифесте и при запуске, с соответствующим разрешением. С Android 12 запуск foreground-сервиса из фона запрещён, кроме исключений.
  • Bound service: клиенты привязываются через bindService и общаются через IBinder, живёт, пока есть привязки.

Сервис по умолчанию выполняется на главном потоке: внутри всё равно нужны корутины или потоки.

WorkManager

Рекомендованное API для отложенной гарантированной работы: она выполнится, даже если приложение закрыли или устройство перезагрузилось.

class SyncWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) {
    override suspend fun doWork(): Result = try {
        repository.sync()
        Result.success()
    } catch (e: IOException) {
        if (runAttemptCount < 5) Result.retry() else Result.failure()
    }
}

val request = OneTimeWorkRequestBuilder<SyncWorker>()
    .setConstraints(Constraints(requiredNetworkType = NetworkType.CONNECTED))
    .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30, TimeUnit.SECONDS)
    .build()

WorkManager.getInstance(context)
    .enqueueUniqueWork("sync", ExistingWorkPolicy.KEEP, request)
  • Ограничения: сеть, зарядка, не низкий заряд, свободное место, простой устройства.
  • PeriodicWorkRequest с минимальным интервалом 15 минут.
  • Уникальная работа (enqueueUniqueWork) защищает от дублей.
  • Цепочки beginWith(a).then(b), входные и выходные данные Data (маленькие, до 10 КБ).
  • Срочная работа: setExpedited(...). Долгая работа с уведомлением: setForeground() внутри воркера.
  • Наблюдение за статусом: getWorkInfoByIdFlow.
  • Хранит задачи в своей базе, под капотом использует JobScheduler.

Чего WorkManager не гарантирует: точное время запуска. Система откладывает работу из-за Doze и App Standby Buckets. Для точного будильника есть AlarmManager.setExactAndAllowWhileIdle (с Android 12 нужен доступ к точным будильникам, а с Android 14 разрешение SCHEDULE_EXACT_ALARM по умолчанию не выдаётся большинству новых приложений).

Как выбрать

ЗадачаИнструмент
Работа, пока пользователь на экранекорутины в viewModelScope
Должно завершиться, даже если экран закрыли, но процесс живapplication-scope
Гарантированно выполнить, можно отложить (синхронизация, загрузка логов)WorkManager
Долгая работа, о которой знает пользователь (музыка, навигация, загрузка файла)foreground service с нужным типом или WorkManager с setForeground
В точное времяAlarmManager

Частые ошибки

  • Сеть или база на главном потоке.
  • Работа, которая должна завершиться, в viewModelScope.
  • Thread.sleep и блокирующие вызовы в Dispatchers.Main.
  • Foreground service без типа на Android 14+.
  • PeriodicWorkRequest с ожиданием интервала меньше 15 минут.
  • enqueue синхронизации при каждом старте без уникального имени: дубли.

Что спросят на собесе

  • Что такое ANR и как его избежать?
  • Как работает главный поток, Looper и Handler?
  • Какие бывают сервисы и какие ограничения появились в новых Android?
  • Когда WorkManager, а когда foreground service?
  • Как WorkManager гарантирует выполнение и что такое constraints?

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.