Основы Android Kotlin 09.2: WorkManager

Эта практическая работа входит в курс «Основы Android Kotlin». Вы получите максимальную пользу от этого курса, если будете выполнять практические работы последовательно. Все практические работы курса перечислены на целевой странице практической работы «Основы Android Kotlin» .

Введение

Большинству реальных приложений необходимо выполнять длительные фоновые задачи. Например, приложение может загружать файлы на сервер, синхронизировать данные с сервера и сохранять их в базе данных Room , отправлять журналы на сервер или выполнять ресурсоёмкие операции с данными. Такие операции должны выполняться в фоновом режиме, вне потока пользовательского интерфейса (главного потока). Фоновые задачи потребляют ограниченные ресурсы устройства, такие как оперативная память и заряд аккумулятора. Неправильная обработка может привести к некомфортному опыту пользователя.

В этой лабораторной работе вы узнаете, как использовать WorkManager для оптимального и эффективного планирования фоновых задач. Подробнее о других доступных решениях для фоновой обработки в Android см. в руководстве по фоновой обработке .

Что вам уже следует знать

  • Как использовать компоненты архитектуры Android ViewModel , LiveData и Room .
  • Как выполнять преобразования в классе LiveData .
  • Как построить и запустить сопрограмму .
  • Как использовать адаптеры привязки при привязке данных.
  • Как загрузить кэшированные данные с использованием шаблона репозитория.

Чему вы научитесь

  • Как создать Worker , представляющий единицу работы.
  • Как создать WorkRequest для запроса на выполнение работы.
  • Как добавить ограничения в WorkRequest , чтобы определить, как и когда должен запускаться работник.
  • Как использовать WorkManager для планирования фоновых задач.

Что ты будешь делать?

  • Создайте рабочий процесс для выполнения фоновой задачи по предварительной загрузке видеоплейлиста DevBytes из сети.
  • Запланируйте периодический запуск рабочего процесса.
  • Добавьте ограничения в WorkRequest .
  • Запланируйте периодический WorkRequest , который будет выполняться раз в день.

В этой лабораторной работе вы будете работать над приложением DevBytes, которое разработали в предыдущей лабораторной работе. (Если у вас нет этого приложения, вы можете загрузить начальный код для этого урока.)

Приложение DevBytes отображает список видеороликов DevByte — коротких обучающих программ, созданных командой Google по работе с разработчиками Android . В видеороликах представлены функции для разработчиков и передовой опыт разработки для Android.

Вы улучшаете пользовательский опыт в приложении, предварительно загружая видео раз в день. Это гарантирует, что пользователь получит свежий контент сразу после открытия приложения.

В этом задании вы загрузите и проверите стартовый код.

Шаг 1: Загрузите и запустите стартовое приложение.

Вы можете продолжить работу с приложением DevBytes, которое вы создали в предыдущей лабораторной работе (если оно у вас есть). Также вы можете скачать стартовое приложение.

В этом задании вы загрузите и запустите стартовое приложение и изучите его код.

  1. Если у вас еще нет приложения DevBytes, загрузите стартовый код DevBytes для этой лабораторной работы из проекта DevBytesRepository на GitHub.
  2. Разархивируйте код и откройте проект в Android Studio.
  3. Подключите тестовое устройство или эмулятор к интернету, если оно ещё не подключено. Соберите и запустите приложение. Приложение загрузит список видео DevByte из сети и отобразит их.
  4. В приложении нажмите на любое видео, чтобы открыть его в приложении YouTube.

Шаг 2: Изучите код

Стартовое приложение содержит большой объём кода, представленного в предыдущей лабораторной работе. Стартовый код для этой лабораторной работы включает модули сети, пользовательского интерфейса, автономного кэширования и репозитория. Вы можете сосредоточиться на планировании фоновой задачи с помощью WorkManager .

  1. В Android Studio разверните все пакеты.
  2. Ознакомьтесь с пакетом database . Пакет содержит сущности базы данных и локальную базу данных, реализованную с помощью Room .
  3. Изучите пакет repository . Он содержит класс VideosRepository , который абстрагирует уровень данных от остальной части приложения.
  4. Изучите остальную часть начального кода самостоятельно и с помощью предыдущей лабораторной работы.

WorkManager — один из компонентов архитектуры Android и часть Android Jetpack . WorkManager предназначен для фоновой работы, которая может быть отложена и требует гарантированного выполнения:

  • Отложенность означает, что работа не требует немедленного выполнения. Например, отправка аналитических данных на сервер или синхронизация базы данных в фоновом режиме — это работа, которую можно отложить.
  • Гарантированное выполнение означает, что задача будет выполнена даже в случае закрытия приложения или перезагрузки устройства.

Выполняя фоновую задачу, WorkManager решает проблемы совместимости и применяет передовые методы для поддержания работоспособности аккумулятора и системы. WorkManager обеспечивает совместимость вплоть до уровня API 14. WorkManager выбирает подходящий способ планирования фоновой задачи в зависимости от уровня API устройства. Он может использовать JobScheduler (на API 23 и выше) или комбинацию AlarmManager и BroadcastReceiver .

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

В этой лабораторной работе вы запланируете задачу предварительной загрузки видеоплейлиста DevBytes из сети один раз в день. Для этого используется библиотека WorkManager .

  1. Откройте файл build.gradle (Module:app) и добавьте зависимость WorkManager к проекту.

    Если вы используете последнюю версию библиотеки, приложение-решение должно скомпилироваться должным образом. Если это не так, попробуйте решить проблему самостоятельно или вернитесь к версии библиотеки, указанной ниже.
// WorkManager dependency
def work_version = "1.0.1"
implementation "android.arch.work:work-runtime-ktx:$work_version"
  1. Синхронизируйте свой проект и убедитесь в отсутствии ошибок компиляции.

Прежде чем добавлять код в проект, ознакомьтесь со следующими классами в библиотеке WorkManager :

  • Worker
    В этом классе определяется фактическая работа (задача), которая будет выполняться в фоновом режиме. Вы расширяете этот класс и переопределяете метод doWork() . В методе doWork() размещается код, который будет выполняться в фоновом режиме, например, синхронизация данных с сервером или обработка изображений. В этой задаче вы реализуете Worker .
  • WorkRequest
    Этот класс представляет запрос на запуск задачи-воркера в фоновом режиме. Используйте WorkRequest для настройки времени и времени запуска задачи-воркера с помощью Constraints , таких как наличие подключенного устройства или подключение к сети Wi-Fi. WorkRequest реализуется в последующей задаче.
  • WorkManager
    Этот класс планирует и выполняет ваш WorkRequest . WorkManager планирует рабочие запросы таким образом, чтобы равномерно распределить нагрузку на системные ресурсы, соблюдая заданные вами ограничения. WorkManager реализуется в последующей задаче.

Шаг 1: Создание работника

В этой задаче вы добавляете Worker для предварительной загрузки видеоплейлиста DevBytes в фоновом режиме.

  1. Внутри пакета devbyteviewer создайте новый пакет с именем work .
  2. Внутри work пакета создайте новый класс Kotlin с именем RefreshDataWorker .
  3. Расширьте класс RefreshDataWorker из класса CoroutineWorker . Передайте context и WorkerParameters в качестве параметров конструктора.
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
       CoroutineWorker(appContext, params) {
}
  1. Чтобы устранить ошибку абстрактного класса, переопределите метод doWork() внутри класса RefreshDataWorker .
override suspend fun doWork(): Result {
  return Result.success()
}

Приостанавливающая функция — это функция, выполнение которой можно приостановить и возобновить позже. Приостанавливающая функция может выполнять длительную операцию и ожидать её завершения, не блокируя основной поток.

Шаг 2: Реализация doWork()

Метод doWork() внутри класса Worker вызывается в фоновом потоке. Метод выполняет работу синхронно и должен возвращать объект ListenableWorker.Result . Система Android даёт Worker максимум 10 минут на завершение выполнения и возврат объекта ListenableWorker.Result . По истечении этого времени система принудительно останавливает Worker .

Чтобы создать объект ListenableWorker.Result , вызовите один из следующих статических методов, чтобы указать статус завершения фоновой работы:

  • Result.success() — работа завершена успешно.
  • Result.failure() — работа завершена с постоянным сбоем.
  • Result.retry() — работа столкнулась с временным сбоем и должна быть повторена.

В этой задаче вы реализуете метод doWork() для извлечения видеоплейлиста DevBytes из сети. Вы можете повторно использовать существующие методы класса VideosRepository для извлечения данных из сети.

  1. В классе RefreshDataWorker внутри doWork() создайте и создайте экземпляры объекта VideosDatabase и объекта VideosRepository .
override suspend fun doWork(): Result {
   val database = getDatabase(applicationContext)
   val repository = VideosRepository(database)

   return Result.success()
}
  1. В классе RefreshDataWorker , внутри doWork() , над оператором return , вызовите метод refreshVideos() в блоке try . Добавьте журнал для отслеживания времени запуска рабочего процесса.
try {
   repository.refreshVideos( )
   Timber.d("Work request for sync is run")
   } catch (e: HttpException) {
   return Result.retry()
}

Чтобы устранить ошибку «Неразрешенная ссылка», импортируйте retrofit2.HttpException .

  1. Ниже для справки представлен полный класс RefreshDataWorker :
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
       CoroutineWorker(appContext, params) {

   override suspend fun doWork(): Result {
       val database = getDatabase(applicationContext)
       val repository = VideosRepository(database)
       try {
           repository.refreshVideos()
       } catch (e: HttpException) {
           return Result.retry()
       }
       return Result.success()
   }
}

Worker определяет единицу работы, а WorkRequest — как и когда должна выполняться работа. Существует две конкретные реализации класса WorkRequest :

  • Класс OneTimeWorkRequest предназначен для одноразовых задач. ( Одноразовая задача выполняется только один раз.)
  • Класс PeriodicWorkRequest предназначен для периодической работы, которая повторяется через определенные промежутки времени.

Задачи могут быть разовыми или периодическими, поэтому выбирайте класс соответственно. Подробнее о планировании повторяющихся задач см. в документации по повторяющимся задачам .

В этой задаче вы определяете и планируете WorkRequest для запуска исполнителя, созданного вами в предыдущей задаче.

Шаг 1: Настройте повторяющуюся работу

В приложении Android класс Application является базовым классом, содержащим все остальные компоненты, такие как действия и сервисы. При создании процесса для вашего приложения или пакета класс Application (или любой Application подкласс) создаётся раньше любого другого класса.

В этом примере приложения класс DevByteApplication является подклассом класса Application . Класс DevByteApplication — хорошее место для планирования WorkManager .

  1. В классе DevByteApplication создайте метод setupRecurringWork() для настройки повторяющейся фоновой работы.
/**
* Setup WorkManager background job to 'fetch' new network data daily.
*/
private fun setupRecurringWork() {
}
  1. В методе setupRecurringWork() создайте и инициализируйте периодический рабочий запрос, который будет выполняться раз в день, используя метод PeriodicWorkRequestBuilder() . Передайте класс RefreshDataWorker , созданный в предыдущей задаче. Передайте интервал повторения 1 с единицей времени TimeUnit. DAYS .
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
       .build()

Чтобы устранить ошибку, импортируйте java.util.concurrent.TimeUnit .

Шаг 2: Запланируйте WorkRequest с помощью WorkManager

После определения WorkRequest вы можете запланировать его выполнение с помощью WorkManager , используя метод enqueueUniquePeriodicWork() . Этот метод позволяет добавить PeriodicWorkRequest с уникальным именем в очередь, где одновременно может быть активен только один PeriodicWorkRequest с определённым именем.

Например, вам может потребоваться активировать только одну операцию синхронизации. Если одна операция синхронизации ожидает выполнения, вы можете разрешить её выполнение или заменить новой работой, используя ExistingPeriodicWorkPolicy .

Дополнительную информацию о способах планирования WorkRequest см. в документации WorkManager .

  1. В начале класса RefreshDataWorker добавьте объект-компаньон. Определите имя для уникальной идентификации этого объекта.
companion object {
   const val WORK_NAME = "com.example.android.devbyteviewer.work.RefreshDataWorker"
}
  1. В классе DevByteApplication , в конце метода setupRecurringWork() , запланируйте работу с помощью метода enqueueUniquePeriodicWork() . Передайте перечисление KEEP для ExistingPeriodicWorkPolicy. Передайте repeatingRequest в качестве параметра PeriodicWorkRequest .
WorkManager.getInstance().enqueueUniquePeriodicWork(
       RefreshDataWorker.WORK_NAME,
       ExistingPeriodicWorkPolicy.KEEP,
       repeatingRequest)

Если существует отложенная (незавершенная) работа с тем же именем, параметр ExistingPeriodicWorkPolicy. заставляет KEEP сохранить предыдущую периодическую работу и отменить новый запрос WorkManager работу.

  1. В начале класса DevByteApplication создайте объект CoroutineScope и передайте Dispatchers.Default в качестве параметра конструктора.
private val applicationScope = CoroutineScope(Dispatchers.Default)
  1. В классе DevByteApplication добавьте новый метод delayedInit() для запуска сопрограммы.
private fun delayedInit() {
   applicationScope.launch {
   }
}
  1. Внутри метода delayedInit() вызовите setupRecurringWork() .
  2. Перенесите инициализацию Timber из метода onCreate() в метод delayedInit() .
private fun delayedInit() {
   applicationScope.launch {
       Timber.plant(Timber.DebugTree())
       setupRecurringWork()
   }
}
  1. В классе DevByteApplication в конце метода onCreate() добавьте вызов метода delayedInit() .
override fun onCreate() {
   super.onCreate()
   delayedInit()
}
  1. Откройте панель Logcat в нижней части окна Android Studio. Отфильтруйте по RefreshDataWorker .
  2. Запустите приложение. WorkManager мгновенно запланирует вашу повторяющуюся работу.

    На панели Logcat обратите внимание на записи журнала, которые показывают, что запрос на работу запланирован, а затем успешно выполнен.
D/RefreshDataWorker: Work request for sync is run
I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]

Журнал WM-WorkerWrapper отображается из библиотеки WorkManager , поэтому вы не можете изменить это сообщение журнала.

Шаг 3: (Необязательно) Запланируйте WorkRequest на минимальный интервал

На этом этапе вы уменьшаете временной интервал с 1 дня до 15 минут. Это делается для того, чтобы можно было увидеть журналы выполнения периодического запроса на выполнение работ.

  1. В классе DevByteApplication , внутри метода setupRecurringWork() , закомментируйте текущее определение repeatingRequest . Добавьте новый запрос на работу с периодическим интервалом повторения 15 минут.
// val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
//        .build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
       .build()
  1. Откройте панель Logcat в Android Studio и отфильтруйте данные по RefreshDataWorker . Чтобы очистить предыдущие журналы, нажмите значок «Очистить Logcat». .
  2. Запустите приложение, и WorkManager немедленно запланирует вашу повторяющуюся работу. На панели Logcat обратите внимание на журналы — запрос на работу выполняется каждые 15 минут. Подождите 15 минут, чтобы увидеть ещё один набор журналов запросов на работу. Вы можете оставить приложение запущенным или закрыть его; менеджер задач должен продолжать работать.

    Обратите внимание, что интервал иногда составляет менее 15 минут, а иногда более 15 минут. (Точное время зависит от оптимизации ОС по расходу заряда батареи.)
12:44:40 D/RefreshDataWorker: Work request for sync is run
12:44:40 I/WM-WorkerWrapper: Worker result SUCCESS for Work 
12:59:24 D/RefreshDataWorker: Work request for sync is run
12:59:24 I/WM-WorkerWrapper: Worker result SUCCESS for Work 
13:15:03 D/RefreshDataWorker: Work request for sync is run
13:15:03 I/WM-WorkerWrapper: Worker result SUCCESS for Work 
13:29:22 D/RefreshDataWorker: Work request for sync is run
13:29:22 I/WM-WorkerWrapper: Worker result SUCCESS for Work 
13:44:26 D/RefreshDataWorker: Work request for sync is run
13:44:26 I/WM-WorkerWrapper: Worker result SUCCESS for Work
 

Поздравляем! Вы создали воркер и запланировали запрос на выполнение работы с помощью WorkManager . Но есть проблема: вы не указали никаких ограничений. WorkManager будет планировать выполнение задачи один раз в день, даже если устройство разряжено, находится в спящем режиме или не подключено к сети. Это повлияет на заряд батареи и производительность устройства, а также может привести к ухудшению пользовательского опыта.

В следующей задаче вы решите эту проблему, добавив ограничения.

В предыдущей задаче вы использовали WorkManager для планирования запроса на работу. В этой задаче вы добавляете критерии времени выполнения работы.

При определении WorkRequest можно указать ограничения на время выполнения Worker . Например, можно указать, что работа должна выполняться только тогда, когда устройство находится в режиме ожидания или только когда оно подключено к сети и Wi-Fi. Вы также можете указать политику отсрочки для повторных попыток выполнения работы. Поддерживаемые ограничения — это методы, заданные в Constraints.Builder . Подробнее см. в разделе «Определение запросов на работу» .

Шаг 1: Добавьте объект «Ограничения» и задайте одно ограничение.

На этом этапе вы создаёте объект Constraints и устанавливаете для него одно ограничение — сетевое. (Лог-файлы легче отслеживать, если задано только одно ограничение. На следующем этапе вы добавите другие ограничения.)

  1. В классе DevByteApplication , в начале метода setupRecurringWork() , определите val типа Constraints . Используйте метод Constraints.Builder() .
val constraints = Constraints.Builder()

Чтобы устранить ошибку, импортируйте androidx.work.Constraints .

  1. Используйте метод setRequiredNetworkType() , чтобы добавить ограничение типа сети к объекту constraints . Используйте перечисление UNMETERED , чтобы запрос на работу выполнялся только при подключении устройства к безлимитной сети.
.setRequiredNetworkType(NetworkType.UNMETERED)
  1. Используйте метод build() для генерации ограничений из построителя.
val constraints = Constraints.Builder()
       .setRequiredNetworkType(NetworkType.UNMETERED)
       .build()

Теперь вам нужно установить только что созданный объект Constraints для запроса на работу.

  1. В классе DevByteApplication , в методе setupRecurringWork() , установите объект Constraints для периодического запроса на работу repeatingRequest . Чтобы установить ограничения, добавьте метод setConstraints() над вызовом метода build() .
       val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
               .setConstraints(constraints)
               .build()

Шаг 2: Запустите приложение и просмотрите журналы.

На этом этапе вы запускаете приложение и замечаете, что ограниченный запрос на работу запускается в фоновом режиме с определенными интервалами.

  1. Удалите приложение с устройства или эмулятора, чтобы отменить все ранее запланированные задачи.
  2. Откройте панель Logcat в Android Studio. На панели Logcat очистите предыдущие журналы, нажав на значок «Очистить Logcat». слева. Фильтр по work .
  3. Отключите Wi-Fi на устройстве или эмуляторе, чтобы увидеть, как работают ограничения. Текущий код устанавливает только одно ограничение, указывающее, что запрос должен выполняться только в безлимитной сети. Поскольку Wi-Fi отключен, устройство не подключено к сети, ни с тарификацией, ни без тарификацией. Следовательно, это ограничение не будет соблюдено.
  4. Запустите приложение и обратите внимание на панель Logcat . WorkManager немедленно планирует фоновую задачу. Поскольку сетевое ограничение не выполнено, задача не запускается.
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled
  1. Включите Wi-Fi на устройстве или эмуляторе и наблюдайте за панелью Logcat . Теперь запланированная фоновая задача запускается примерно каждые 15 минут, пока соблюдаются ограничения сети.
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled
11:31:47 D/RefreshDataWorker: Work request for sync is run
11:31:47 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]
11:46:45 D/RefreshDataWorker: Work request for sync is run
11:46:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 
12:03:05 D/RefreshDataWorker: Work request for sync is run
12:03:05 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 
12:16:45 D/RefreshDataWorker: Work request for sync is run
12:16:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 
12:31:45 D/RefreshDataWorker: Work request for sync is run
12:31:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 
12:47:05 D/RefreshDataWorker: Work request for sync is run
12:47:05 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 
13:01:45 D/RefreshDataWorker: Work request for sync is run
13:01:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]

Шаг 3: Добавьте больше ограничений

На этом этапе вы добавляете следующие ограничения в PeriodicWorkRequest :

  • Батарея не разряжена.
  • Зарядка устройства.
  • Устройство находится в режиме ожидания; доступно только в API уровня 23 (Android M) и выше.

Реализуйте следующее в классе DevByteApplication .

  1. В классе DevByteApplication в методе setupRecurringWork() укажите, что запрос на выполнение работы должен выполняться только при достаточном уровне заряда батареи. Добавьте ограничение перед вызовом метода build() и используйте метод setRequiresBatteryNotLow() .
.setRequiresBatteryNotLow(true)
  1. Обновите запрос на выполнение так, чтобы он выполнялся только во время зарядки устройства. Добавьте ограничение перед вызовом метода build() и используйте метод setRequiresCharging() .
.setRequiresCharging(true)
  1. Обновите запрос на выполнение так, чтобы он выполнялся только при бездействии устройства. Добавьте ограничение перед вызовом метода build() и используйте метод setRequiresDeviceIdle() . Это ограничение запускает запрос на выполнение только тогда, когда пользователь не использует устройство активно. Эта функция доступна только в Android 6.0 (Marshmallow) и более поздних версиях, поэтому добавьте условие для версии SDK M и выше.
.apply {
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
       setRequiresDeviceIdle(true)
   }
}

Вот полное определение объекта constraints .

val constraints = Constraints.Builder()
       .setRequiredNetworkType(NetworkType.UNMETERED)
       .setRequiresBatteryNotLow(true)
       .setRequiresCharging(true)
       .apply {
           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
               setRequiresDeviceIdle(true)
           }
       }
       .build()
  1. Внутри метода setupRecurringWork() измените интервал запроса обратно на один раз в день.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
       .setConstraints(constraints)
       .build()

Ниже представлена полная реализация метода setupRecurringWork() с журналом, позволяющим отслеживать, когда запланирован периодический запрос на работу.

private fun setupRecurringWork() {

       val constraints = Constraints.Builder()
               .setRequiredNetworkType(NetworkType.UNMETERED)
               .setRequiresBatteryNotLow(true)
               .setRequiresCharging(true)
               .apply {
                   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                       setRequiresDeviceIdle(true)
                   }
               }
               .build()
       val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
               .setConstraints(constraints)
               .build()
       
       Timber.d("Periodic Work request for sync is scheduled")
       WorkManager.getInstance().enqueueUniquePeriodicWork(
               RefreshDataWorker.WORK_NAME,
               ExistingPeriodicWorkPolicy.KEEP,
               repeatingRequest)
   }
  1. Чтобы удалить ранее запланированный запрос на работу, удалите приложение DevBytes со своего устройства или эмулятора.
  2. Запустите приложение, и WorkManager немедленно запланирует запрос на работу. Запрос на работу будет выполняться один раз в день при соблюдении всех ограничений.
  3. Этот рабочий запрос будет выполняться в фоновом режиме, пока установлено приложение, даже если оно не запущено. Поэтому вам следует удалить приложение с телефона.

Отличная работа! Вы реализовали и запланировали экономичный для батареи запрос на ежедневную предварительную загрузку видео в приложении DevBytes. WorkManager запланирует и выполнит эту задачу, оптимизируя системные ресурсы. Ваши пользователи и их аккумуляторы будут очень довольны.

Проект Android Studio: DevBytesWorkManager .

  • API WorkManager упрощает планирование откладываемых асинхронных задач, которые должны выполняться надежно.
  • Большинству реальных приложений необходимо выполнять длительные фоновые задачи. Для оптимального и эффективного планирования фоновой задачи используйте WorkManager .
  • Основными классами в библиотеке WorkManager являются Worker , WorkRequest и WorkManager .
  • Класс Worker представляет единицу работы. Чтобы реализовать фоновую задачу, расширьте класс Worker и переопределите метод doWork() .
  • Класс WorkRequest представляет собой запрос на выполнение единицы работы. WorkRequest — базовый класс для указания параметров работы, которую вы планируете в WorkManager .
  • Существуют две конкретные реализации класса WorkRequest : OneTimeWorkRequest для разовых задач и PeriodicWorkRequest для периодических запросов на работу.
  • При определении WorkRequest можно указать Constraints указывающие, когда следует запускать Worker . Ограничения включают в себя, например, подключено ли устройство к сети, находится ли оно в режиме ожидания или подключено ли к сети Wi-Fi.
  • Чтобы добавить ограничения к WorkRequest , используйте методы set, перечисленные в документации Constraints.Builder . Например, чтобы указать, что WorkRequest не должен запускаться при низком заряде батареи устройства, используйте метод set set setRequiresBatteryNotLow() .
  • После определения WorkRequest передайте задачу системе Android. Для этого запланируйте её выполнение с помощью одного из методов enqueue WorkManager .
  • Точное время выполнения Worker зависит от ограничений, используемых в WorkRequest , и от системных оптимизаций. WorkManager разработан для обеспечения наилучшего поведения с учётом этих ограничений.

Курс Udacity:

Документация для разработчиков Android:

Другой:

В этом разделе перечислены возможные домашние задания для студентов, работающих над этой лабораторной работой в рамках курса, проводимого преподавателем. Преподаватель должен выполнить следующие действия:

  • При необходимости задавайте домашнее задание.
  • Объясните учащимся, как следует сдавать домашние задания.
  • Оцените домашние задания.

Преподаватели могут использовать эти предложения так часто или редко, как пожелают, и могут свободно задавать любые другие домашние задания, которые они сочтут подходящими.

Если вы работаете с этой лабораторной работой самостоятельно, можете использовать эти домашние задания для проверки своих знаний.

Вопрос 1

Каковы конкретные реализации класса WorkRequest ?

OneTimeWorkPeriodicRequest

OneTimeWorkRequest и PeriodicWorkRequest

OneTimeWorkRequest и RecurringWorkRequest

OneTimeOffWorkRequest и RecurringWorkRequest

Вопрос 2

Какой из следующих классов WorkManager использует для планирования фоновой задачи в API 23 и выше?

▢ Только JobScheduler

BroadcastReceiver и AlarmManager

AlarmManager и JobScheduler

Scheduler и BroadcastReceiver

Вопрос 3

Какой API вы используете для добавления ограничений в WorkRequest ?

setConstraints()

addConstraints()

setConstraint()

addConstraintsToWorkRequest()

Перейти к следующему уроку: 10.1 Стили и темы

Ссылки на другие практические занятия по этому курсу см. на целевой странице практических занятий по основам Android Kotlin .