Диспетчер заданий Firebase
В этом руководстве описано, как планировать фоновую работу с помощью библиотеки диспетчера заданий Firebase от Google.
Обзор
Один из лучших способов поддерживать хорошую отзывчивость приложения Android — выполнять сложную или длительную работу в фоновом режиме. При этом важно, чтобы фоновая работа не влияла негативно на взаимодействие пользователя с устройством.
Например, фоновое задание может опрашивать веб-сайт каждые три или четыре минуты, чтобы получать изменения в определенном наборе данных. Это кажется пустяком, но это может повлиять на время работы аккумулятора. Приложение будет раз за разом выводить устройство из спящего режима, повышать уровень энергопотребления ЦП, включать беспроводную связь, выполнять сетевые запросы и обрабатывать результаты. Все усложняется тем, что устройство не будет немедленно выключаться и возвращаться в режим ожидания с низким энергопотреблением. Плохо спланированная фоновая работа может привести к тому, что устройство самопроизвольно и без необходимости будет переходить в режим повышенного энергопотребления. На первый взгляд безобидное действие (опрос веб-сайта) довольно быстро сделает устройство непригодным для использования.
Android предоставляет приведенные ниже API для выполнения работы в фоновом режиме, но их недостаточно для интеллектуального планирования заданий.
- Службы намерений — службы намерений отлично подходят для выполнения работы, однако они не предоставляют никаких способов планирования работы.
- AlarmManager — эти API позволяют планировать работу только, но не предоставляют возможности фактически выполнять работу. Кроме того, AlarmManager поддерживает только ограничения на основе времени, то есть создает оповещение в определенное время или по истечении определенного времени.
- JobScheduler — JobSchedule — отличный API, который работает с операционной системой для планирования заданий. Однако он доступен только для тех приложений Android, которые нацелены на уровень API 21 или более поздней версии.
- Широковещательные приемники — приложение Android может настроить широковещательные приемники для выполнения работы в ответ на системные события или намерения. При этом широковещательные приемники не позволяют управлять временем выполнения заданий. Кроме того, изменения в операционной системе Android в будущем ограничат возможность выполнять широковещательные приемники, а также типы работы, на которую они могут реагировать.
Существуют два ключевых аспекта эффективного выполнения фоновой работы (иногда называемой фоновым заданием или просто заданием):
- Интеллектуальное планирование работы — важно, чтобы, когда приложение выполняет работу в фоновом режиме, что делает это как хороший гражданин. В идеале приложение не должно требовать выполнения задания. Вместо этого оно должно указать условия, при которых задание может быть выполнено, а затем запланировать выполнение работы при выполнении этих условий. Это позволяет Android выполнять работу интеллектуально. Например, сетевые запросы могут собираться в пакет и выполняться одновременно, чтобы оптимизировать затраты на работу с сетью.
- Инкапсулируя работу. Код для выполнения фоновой работы должен быть инкапсулирован в дискретном компоненте, который может выполняться независимо от пользовательского интерфейса и будет относительно легко перепланировать работу, если работа не завершится по какой-то причине.
Диспетчер заданий Firebase — это библиотека от Google, которая предоставляет текучий API для упрощения планирования фоновой работы. Она должна заменить Google Cloud Manager. Диспетчер заданий Firebase содержит следующие интерфейсы API.
Firebase.JobDispatcher.JobService
— это абстрактный класс, который должен быть расширен с помощью логики, которая будет выполняться в фоновом задании.Firebase.JobDispatcher.JobTrigger
объявляет, когда задание должно быть запущено. Обычно это период времени, например, ожидание не менее 30 секунд перед запуском задания, но при этом задание должно быть запущено в течение 5 минут.Firebase.JobDispatcher.RetryStrategy
содержит сведения о том, что следует делать, если задание не выполняется должным образом. Стратегия повтора указывает время ожидания перед повторной попыткой выполнения задания.Firebase.JobDispatcher.Constraint
— это необязательное значение, описывающее условие, которое должно быть выполнено для запуска задания. Например, устройство не должно находиться в сети с оплатой трафика или заряжаться.Firebase.JobDispatcher.Job
— это API, который объединяет предыдущие API в единицу работы, которую может запланироватьJobDispatcher
. КлассJob.Builder
используется для создания экземпляраJob
.Firebase.JobDispatcher.JobDispatcher
использует три описанных выше API, чтобы планировать работу с помощью операционной системой и предоставить способ отмены заданий, если это потребуется.
Чтобы запланировать работу с помощью диспетчера заданий Firebase, приложение Xamarin.Android должно инкапсулировать код в типе, который расширяет класс JobService
. JobService
содержит три метода жизненного цикла, которые могут быть вызваны в течение времени существования задания.
bool OnStartJob(IJobParameters parameters)
— Этот метод заключается в том, где будут выполняться работы и всегда должны быть реализованы. Он выполняется в основном потоке. Этот метод возвращаетtrue
, если работа еще не выполнена, иfalse
, если она завершена.bool OnStopJob(IJobParameters parameters)
— Это вызывается, когда задание останавливается по какой-то причине. Он должен возвращатьtrue
, если задание следует повторно запланировать.JobFinished(IJobParameters parameters, bool needsReschedule)
— Этот метод вызывается приJobService
завершении любой асинхронной работы.
Чтобы запланировать задание, приложение создаст экземпляр объекта JobDispatcher
. Затем Job.Builder
используется для создания объекта Job
. Этот объект предоставляется JobDispatcher
, который попытается запланировать выполнение задания.
В этом руководство описано, как добавить диспетчер заданий Firebase в приложение Xamarin.Android и использовать его для планирования фоновой работы.
Требования
Диспетчеру заданий Firebase требуется уровень API Android 9 или более поздней версии. Библиотека диспетчера заданий Firebase использует некоторые компоненты, предоставляемые Сервисами Google Play, поэтому устройстве должны быть установлены Сервисы Google Play.
Использование библиотеки диспетчера заданий Firebase в Xamarin.Android
Чтобы приступить к работе с диспетчером заданий Firebase, сначала добавьте пакет NuGet Xamarin.Firebase.JobDispatcher в проект Xamarin.Android. Найдите в диспетчере пакетов NuGet пакет Xamarin.Firebase.JobDispatcher (который пока находится на этапе предварительной версии).
После добавления библиотеки диспетчера заданий Firebase создайте класс JobService
и запланируйте его запуск с помощью экземпляра FirebaseJobDispatcher
.
Создание JobService
Вся работа, выполняемая библиотекой диспетчера заданий Firebase, должна быть выполнена в типе, расширяющем абстрактный класс Firebase.JobDispatcher.JobService
. Создание JobService
очень похоже на создание Service
с помощью платформы Android.
- Расширьте класс
JobService
. - Декорируйте подкласс с помощью
ServiceAttribute
. Хотя это и не обязательно, рекомендуется явно задать параметрName
, чтобы упростить отладкуJobService
. - Добавьте
IntentFilter
, чтобы объявитьJobService
в AndroidManifest.xml. Это также поможет библиотеке диспетчера заданий Firebase найти и вызватьJobService
.
Следующий код является примером простейшего JobService
для приложения, использующего TPL для асинхронного выполнения некоторой работы.
[Service(Name = "com.xamarin.fjdtestapp.DemoJob")]
[IntentFilter(new[] {FirebaseJobServiceIntent.Action})]
public class DemoJob : JobService
{
static readonly string TAG = "X:DemoService";
public override bool OnStartJob(IJobParameters jobParameters)
{
Task.Run(() =>
{
// Work is happening asynchronously (code omitted)
});
// Return true because of the asynchronous work
return true;
}
public override bool OnStopJob(IJobParameters jobParameters)
{
Log.Debug(TAG, "DemoJob::OnStartJob");
// nothing to do.
return false;
}
}
Создание FirebaseJobDispatcher
Прежде чем можно будет запланировать работу, необходимо создать объект Firebase.JobDispatcher.FirebaseJobDispatcher
. FirebaseJobDispatcher
отвечает за планирование JobService
. В следующем фрагменте кода показан один из способов создания экземпляра FirebaseJobDispatcher
.
// This is the "Java" way to create a FirebaseJobDispatcher object
IDriver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);
В предыдущем фрагменте кода GooglePlayDriver
— это класс, помогающий FirebaseJobDispatcher
взаимодействовать с некоторыми API планирования в Сервисах Google Play на устройстве. Параметр context
— это любой Context
Android, например действие. Сейчас GooglePlayDriver
является единственной реализацией IDriver
в библиотеке диспетчера заданий Firebase.
Привязка Xamarin.Android для диспетчера заданий Firebase обеспечивает метод расширения для создания FirebaseJobDispatcher
из Context
.
FirebaseJobDispatcher dispatcher = context.CreateJobDispatcher();
После создания экземпляра FirebaseJobDispatcher
можно создать Job
и выполнить код в классе JobService
. Job
создается объектом Job.Builder
и будет рассмотрен в следующем разделе.
Создание Firebase.JobDispatcher.Job с помощью Job.Builder
Класс Firebase.JobDispatcher.Job
отвечает за инкапсуляцию метаданных, необходимых для запуска JobService
. Job
содержит такие сведения, как любые ограничения, которые должны быть соблюдены для выполнения задания, если Job
повторяется или для выполнения задания используются триггеры. Как минимум, Job
должен содержать тег (уникальная строка, указывающая задание для FirebaseJobDispatcher
) и тип выполняемого объекта JobService
. Диспетчер заданий Firebase создаст экземпляр JobService
, когда наступит время запуска задания. Job
создается с помощью экземпляра класса Firebase.JobDispatcher.Job.JobBuilder
.
Следующий фрагмент кода является простым примером создания Job
с помощью привязки Xamarin.Android.
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.Build();
Job.Builder
выполнит несколько простых проверок входных значений для задания. Если Job.Builder
не удастся создать Job
, будет порождено исключение. Job.Builder
создаст Job
со следующими параметрами по умолчанию.
- Время
Job
существования (как долго оно будет запланировано на выполнение) только до перезагрузки устройства — после перезагрузкиJob
устройства устройство теряется. - Не
Job
повторяется — он будет выполняться только один раз. - Запуск
Job
будет запланирован как можно скорее. - Стратегия повтора по умолчанию для
Job
заключается в использовании экспоненциальной задержки (см. дополнительные сведения ниже в разделе Настройка RetryStrategy).
Планирование задания
После создания Job
его необходимо запланировать с помощью FirebaseJobDispatcher
, прежде чем выполнять. Запланировать Job
можно двумя способами.
// This will throw an exception if there was a problem scheduling the job
dispatcher.MustSchedule(myJob);
// This method will not throw an exception; an integer result value is returned
int scheduleResult = dispatcher.Schedule(myJob);
Значение, возвращаемое FirebaseJobDispatcher.Schedule
, будет одним из следующих целочисленных значений:
FirebaseJobDispatcher.ScheduleResultSuccess
Job
— Успешно запланировано.FirebaseJobDispatcher.ScheduleResultUnknownError
— Возникла неизвестная проблема, из-за которой неJob
было запланировано.FirebaseJobDispatcher.ScheduleResultNoDriverAvailable
— НедопустимыйIDriver
использовался илиIDriver
каким-то образом недоступен.FirebaseJobDispatcher.ScheduleResultUnsupportedTrigger
— НеTrigger
поддерживается.FirebaseJobDispatcher.ScheduleResultBadService
— служба настроена неправильно или недоступна.
Настройка задания
Задание можно настроить. Ниже приведены примеры того, как можно настроить задание.
- Передача параметров заданию — может
Job
потребоваться дополнительное значение для выполнения своей работы, например скачивание файла. - Задать ограничения . Может потребоваться выполнить задание только при выполнении определенных условий. Например, может потребоваться запускать
Job
только при зарядке устройства. - Укажите, когда
Job
должен выполняться диспетчер заданий Firebase, позволяет приложениям указывать время выполнения задания. - Объявите стратегию повторных попыток для неудачных заданий. Стратегия повторных попыток предоставляет рекомендации по
FirebaseJobDispatcher
тому, что делать сJobs
этим сбоем.
В следующих разделах каждая из этих тем рассматривается более подробно.
Передача параметров в задание
Параметры передаются в задание путем создания Bundle
, который передается вместе с методом Job.Builder.SetExtras
.
Bundle jobParameters = new Bundle();
jobParameters.PutInt(FibonacciCalculatorJob.FibonacciPositionKey, 25);
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetExtras(jobParameters)
.Build();
Доступ к Bundle
осуществляется из свойства IJobParameters.Extras
метода OnStartJob
.
public override bool OnStartJob(IJobParameters jobParameters)
{
int position = jobParameters.Extras.GetInt(FibonacciPositionKey, DEFAULT_VALUE);
// rest of code omitted
}
Установка ограничений
Ограничения могут снизить расходы или истощение аккумулятора на устройстве. Класс Firebase.JobDispatcher.Constraint
определяет эти ограничения как целочисленные значения.
Constraint.OnUnmeteredNetwork
— только запустите задание, если устройство подключено к неметриченной сети. Это удобно, чтобы пользователи не переплачивали за передачу данных.Constraint.OnAnyNetwork
— Запустите задание в любой сети, к которому подключено устройство. Если указано вместе сConstraint.OnUnmeteredNetwork
, то это значение будет иметь приоритет.Constraint.DeviceCharging
— Запустите задание только в том случае, если устройство зарядится.
Ограничения задаются с помощью метода Job.Builder.SetConstraint
.
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetConstraint(Constraint.DeviceCharging)
.Build();
JobTrigger
предоставляет инструкции операционной системе о том, когда должно начаться выполнение задания. У JobTrigger
есть период выполнения, который определяет запланированное время выполнения Job
. У периода выполнения имеются значения периода начала и периода конца. Период начала — это количество секунд, которое устройство должно ожидать перед выполнением задания, а период конца — это максимальное число секунд ожидания перед запуском Job
.
JobTrigger
можно создать с помощью метода Firebase.Jobdispatcher.Trigger.ExecutionWindow
. Например, Trigger.ExecutionWindow(15,60)
означает, что задание должно быть запущено через 15–60 секунд после времени, на которое оно запланировано. Используется метод Job.Builder.SetTrigger
.
JobTrigger myTrigger = Trigger.ExecutionWindow(15,60);
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetTrigger(myTrigger)
.Build();
JobTrigger
по умолчанию для задания представлен значением Trigger.Now
, которое указывает, что задание должно быть запущено как можно быстрее после того, как оно запланировано.
Настройка RetryStrategy
Firebase.JobDispatcher.RetryStrategy
используется для указания того, какую задержку должно использовать устройство, прежде чем пытаться повторно запустить невыполненное задание. У RetryStrategy
имеется политика, которая определяет временной алгоритм, который будет использоваться для повторного планирования невыполненного задания, и период выполнения, на который это задание должно быть запланировано. Данные период повторного планирования определяется двумя значениями. Первое значение — это время ожидания в секундах перед повторным планированием задания (значение начальной задержки). Второе число — это максимальное время в секундах, по истечении которого задание должно быть запущено (значение максимальной задержки).
Два типа политик повтора определяют приведенные ниже целочисленные значения.
RetryStrategy.RetryPolicyExponential
— Экспоненциальная политика обратной передачи увеличит начальное значение обратной передачи экспоненциально после каждого сбоя. При первом сбое задания библиотека ожидает _initial интервала, указанного перед перепланированием задания, например 30 секунд. При второй неудаче библиотека будет ожидать не менее 60 секунд перед попыткой повторного запуска. После третьей неудачной попытки библиотека будет ждать 120 секунд и т. д.RetryStrategy
по умолчанию для библиотеки диспетчера заданий Firebase представляет объектRetryStrategy.DefaultExponential
. Он использует начальную задержку в 30 секунд и максимальную задержку в 3600 секунд.RetryStrategy.RetryPolicyLinear
— Эта стратегия представляет собой линейную обратную передачу , которую задание должно быть перепланировано для выполнения с заданными интервалами (до тех пор, пока задание не будет выполнено успешно). Линейная задержка лучше всего подходит для работы, которая должна быть выполнена как можно скорее, или при наличии проблем, которые быстро исчезают сами по себе. Библиотека диспетчера заданий Firebase определяетRetryStrategy.DefaultLinear
с периодом повторного планирования от 30 до 3600 секунд.
Можно определить пользовательскую стратегию RetryStrategy
с помощью метода FirebaseJobDispatcher.NewRetryStrategy
. Он принимает три параметра.
int policy
— политика является одним из предыдущихRetryStrategy
значений илиRetryStrategy.RetryPolicyLinear
RetryStrategy.RetryPolicyExponential
.int initialBackoffSeconds
— начальная обратная передача — это задержка в секундах, которая требуется перед попыткой повторного выполнения задания. По умолчанию это значение равно 30 секундам.int maximumBackoffSeconds
— максимальное значение отката объявляет максимальное количество секунд, которое необходимо отложить перед попыткой повторного выполнения задания. Значение по умолчанию — 3600 секунд.
RetryStrategy retry = dispatcher.NewRetryStrategy(RetryStrategy.RetryPolicyLinear, initialBackoffSeconds, maximumBackoffSet);
// Create a Job and set the RetryStrategy via the Job.Builder
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetRetryStrategy(retry)
.Build();
Отмена задания
Можно отменить все запланированные задания или только одно задание, используя метод FirebaseJobDispatcher.CancelAll()
или метод FirebaseJobDispatcher.Cancel(string)
.
int cancelResult = dispatcher.CancelAll();
// to cancel a single job:
int cancelResult = dispatcher.Cancel("unique-tag-for-job");
Любой из этих методов возвращает целочисленное значение.
FirebaseJobDispatcher.CancelResultSuccess
— Задание было успешно отменено.FirebaseJobDispatcher.CancelResultUnknownError
— Ошибка предотвратила отмену задания.FirebaseJobDispatcher.CancelResult.NoDriverAvailable
— НеFirebaseJobDispatcher
удается отменить задание, так как не существует допустимогоIDriver
значения.
Итоги
В этом руководство описано, как использовать диспетчер заданий Firebase для интеллектуального выполнения работы в фоновом режиме. Мы изучили, как инкапсулировать в JobService
работу, которую необходимо выполнить, и как с помощью FirebaseJobDispatcher
запланировать эту работу, указывая критерии в JobTrigger
и способ обработки ошибок в RetryStrategy
.