Dyspozytor zadań rozwiązania Firebase
W tym przewodniku omówiono sposób planowania pracy w tle przy użyciu biblioteki Firebase Job Dispatcher firmy Google.
Omówienie
Jednym z najlepszych sposobów reagowania aplikacji systemu Android na użytkownika jest zapewnienie, że złożone lub długotrwałe prace są wykonywane w tle. Jednak ważne jest, aby praca w tle nie wpływała negatywnie na środowisko użytkownika z urządzeniem.
Na przykład zadanie w tle może sondować witrynę internetową co trzy lub cztery minuty, aby wykonać zapytanie o zmiany w określonym zestawie danych. Wydaje się to łagodne, jednak miałoby to katastrofalny wpływ na żywotność baterii. Aplikacja będzie wielokrotnie wznawiać urządzenie, podnieść poziom procesora CPU do wyższego stanu zasilania, włączyć urządzenia radiowe, wysyłać żądania sieciowe, a następnie przetwarzać wyniki. Pogarsza się, ponieważ urządzenie nie będzie natychmiast zasilać i wracać do stanu bezczynności o niskiej mocy. Nieprawidłowo zaplanowane prace w tle mogą przypadkowo zachować urządzenie w stanie z niepotrzebnymi i nadmiernymi wymaganiami dotyczącymi zasilania. Ta pozornie niewinna aktywność (sondowanie witryny internetowej) sprawi, że urządzenie będzie bezużyteczne w stosunkowo krótkim czasie.
System Android udostępnia następujące interfejsy API, które ułatwiają wykonywanie pracy w tle, ale same w sobie nie są wystarczające do inteligentnego planowania zadań.
- Intent Services — usługi Intent Services doskonale nadają się do wykonywania pracy, ale nie zapewniają możliwości planowania pracy.
- AlarmManager — te interfejsy API zezwalają tylko na zaplanowanie pracy, ale nie zapewniają możliwości rzeczywistego wykonania pracy. Ponadto menedżer alarmów zezwala tylko na ograniczenia oparte na czasie, co oznacza zgłaszanie alarmu w określonym czasie lub po upływie określonego czasu.
- JobScheduler — usługa JobSchedule to doskonały interfejs API, który współdziała z systemem operacyjnym w celu planowania zadań. Jednak jest ona dostępna tylko dla tych aplikacji systemu Android, które są przeznaczone dla interfejsu API na poziomie 21 lub wyższym.
- Odbiorniki rozgłaszań — aplikacja systemu Android może skonfigurować odbiorniki emisji w celu wykonywania pracy w odpowiedzi na zdarzenia lub intencje dla całego systemu. Jednak odbiorniki emisji nie zapewniają żadnej kontroli nad tym, kiedy zadanie powinno zostać uruchomione. Zmiany w systemie operacyjnym Android będą również ograniczać, gdy odbiorniki emisji będą działać lub rodzaje pracy, na które mogą reagować.
Istnieją dwie kluczowe funkcje wydajnego wykonywania pracy w tle (czasami określane jako zadanie w tle lub zadanie):
- Inteligentne planowanie pracy — ważne jest, aby aplikacja wykonywała pracę w tle, co robi jako dobry obywatel. Najlepiej, aby aplikacja nie wymagała uruchomienia zadania. Zamiast tego aplikacja powinna określać warunki, które muszą zostać spełnione, gdy zadanie może zostać uruchomione, a następnie zaplanować pracę do uruchomienia po spełnieniu warunków. Dzięki temu system Android może inteligentnie wykonywać pracę. Na przykład żądania sieciowe mogą być wsadowe do uruchamiania wszystkich w tym samym czasie, aby maksymalnie wykorzystać obciążenie związane z siecią.
- Hermetyzowanie pracy — kod do wykonania pracy w tle powinien być hermetyzowany w dyskretnym składniku, który można uruchomić niezależnie od interfejsu użytkownika i będzie stosunkowo łatwy do ponownego przygotowania, jeśli praca nie zostanie ukończona z jakiegoś powodu.
Dyspozytor zadań Firebase to biblioteka firmy Google, która zapewnia płynny interfejs API, aby uprościć planowanie pracy w tle. Jest on przeznaczony do zastąpienia usługi Google Cloud Manager. Dyspozytor zadań Firebase składa się z następujących interfejsów API:
- A
Firebase.JobDispatcher.JobService
to abstrakcyjna klasa, która musi zostać rozszerzona o logikę, która będzie uruchamiana w zadaniu w tle. - Element
Firebase.JobDispatcher.JobTrigger
deklaruje, kiedy zadanie powinno zostać uruchomione. Zwykle jest to wyrażone jako przedział czasu, na przykład poczekaj co najmniej 30 sekund przed uruchomieniem zadania, ale uruchom zadanie w ciągu 5 minut. - Element
Firebase.JobDispatcher.RetryStrategy
zawiera informacje o tym, co należy wykonać, gdy zadanie nie powiedzie się prawidłowo. Strategia ponawiania prób określa czas oczekiwania przed ponownym uruchomieniem zadania. - Jest
Firebase.JobDispatcher.Constraint
to opcjonalna wartość, która opisuje warunek, który musi zostać spełniony przed uruchomieniem zadania, takiego jak urządzenie, znajduje się w niemetrycznej sieci lub ładowaniu. - Jest
Firebase.JobDispatcher.Job
to interfejs API, który łączy poprzednie interfejsy API z jednostką pracy, którą można zaplanować za pomocą poleceniaJobDispatcher
. KlasaJob.Builder
służy do tworzenia wystąpienia klasyJob
. - Funkcja
Firebase.JobDispatcher.JobDispatcher
używa poprzednich trzech interfejsów API do planowania pracy z systemem operacyjnym i zapewnienia sposobu anulowania zadań, jeśli jest to konieczne.
Aby zaplanować pracę z dyspozytorem zadań Firebase, aplikacja platformy Xamarin.Android musi hermetyzować kod w typie rozszerzającym klasę JobService
. JobService
ma trzy metody cyklu życia, które mogą być wywoływane w okresie istnienia zadania:
bool OnStartJob(IJobParameters parameters)
— Ta metoda polega na tym, że nastąpi praca i zawsze powinna zostać wdrożona. Działa on w głównym wątku. Ta metoda zwróci wartośćtrue
, jeśli pozostała praca lubfalse
czy praca zostanie wykonana.bool OnStopJob(IJobParameters parameters)
— Jest to wywoływane, gdy zadanie zostanie zatrzymane z jakiegoś powodu. Powinno ono zostać zwróconetrue
, jeśli zadanie powinno zostać ponownie ułożone na później.JobFinished(IJobParameters parameters, bool needsReschedule)
— Ta metoda jest wywoływana po zakończeniuJobService
dowolnej pracy asynchronicznej.
Aby zaplanować zadanie, aplikacja utworzy wystąpienie JobDispatcher
obiektu. Job.Builder
Następnie element jest używany do utworzenia Job
obiektu, który jest dostarczany do JobDispatcher
polecenia , który spróbuje zaplanować uruchomienie zadania.
W tym przewodniku omówiono sposób dodawania dyspozytora zadań firebase do aplikacji platformy Xamarin.Android i używania jej do planowania pracy w tle.
Wymagania
Dyspozytor zadań Firebase wymaga interfejsu API systemu Android na poziomie 9 lub wyższym. Biblioteka Dyspozytora zadań Firebase opiera się na niektórych składnikach udostępnianych przez usługi Google Play; urządzenie musi mieć zainstalowane usługi Google Play.
Korzystanie z biblioteki dyspozytora zadań Firebase w środowisku Xamarin.Android
Aby rozpocząć pracę z dyspozytorem zadań Firebase, najpierw dodaj pakiet NuGet Xamarin.Firebase.JobDispatcher do projektu Xamarin.Android. Wyszukaj Menedżer pakietów NuGet dla pakietu Xamarin.Firebase.JobDispatcher (który jest nadal w wersji wstępnej).
Po dodaniu biblioteki Firebase Job Dispatcher utwórz klasę JobService
, a następnie zaplanuj jej uruchomienie przy użyciu wystąpienia klasy FirebaseJobDispatcher
.
Tworzenie usługi zadań
Wszystkie prace wykonywane przez bibliotekę Dyspozytora zadań firebase muszą być wykonywane w typie rozszerzającym klasę abstrakcyjną Firebase.JobDispatcher.JobService
. Tworzenie elementu JobService
jest bardzo podobne do tworzenia za Service
pomocą platformy systemu Android:
- Rozszerzanie
JobService
klasy - Udekoruj podklasę za pomocą klasy
ServiceAttribute
. Chociaż nie jest to ściśle wymagane, zaleca się jawne ustawienie parametruName
w celu ułatwienia debugowania elementuJobService
. - Dodaj element ,
IntentFilter
aby zadeklarować elementJobService
w AndroidManifest.xml. Pomoże to również w zlokalizowaniu i wywołaniu biblioteki dyspozytora zadań firebase i wywołaniu poleceniaJobService
.
Poniższy kod jest przykładem najprostszego JobService
dla aplikacji, używając języka TPL do asynchronicznego wykonywania pewnych zadań:
[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;
}
}
Tworzenie bazy danych FirebaseJobDispatcher
Zanim będzie można zaplanować pracę, należy utworzyć Firebase.JobDispatcher.FirebaseJobDispatcher
obiekt. Jest FirebaseJobDispatcher
odpowiedzialny za zaplanowanie elementu JobService
. Poniższy fragment kodu jest jednym ze sposobów utworzenia wystąpienia elementu FirebaseJobDispatcher
:
// This is the "Java" way to create a FirebaseJobDispatcher object
IDriver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);
W poprzednim fragmencie kodu jest to klasa, GooglePlayDriver
która ułatwia interakcję FirebaseJobDispatcher
z niektórymi interfejsami API planowania w usługach Google Play na urządzeniu. Parametr context
jest dowolnym systemem Android Context
, takim jak działanie. GooglePlayDriver
Obecnie jest jedyną implementacją IDriver
w bibliotece Firebase Job Dispatcher.
Powiązanie platformy Xamarin.Android dla dyspozytora zadań firebase udostępnia metodę rozszerzenia umożliwiającą FirebaseJobDispatcher
utworzenie elementu na podstawie elementu Context
:
FirebaseJobDispatcher dispatcher = context.CreateJobDispatcher();
Po utworzeniu FirebaseJobDispatcher
wystąpienia obiektu można utworzyć Job
i uruchomić kod w JobService
klasie . Obiekt Job
jest tworzony przez Job.Builder
obiekt i zostanie omówiony w następnej sekcji.
Tworzenie pliku Firebase.JobDispatcher.Job za pomocą narzędzia Job.Builder
Klasa Firebase.JobDispatcher.Job
jest odpowiedzialna za hermetyzowanie metadanych niezbędnych do uruchomienia klasy JobService
. ElementJob
zawiera informacje, takie jak wszelkie ograniczenia, które muszą zostać spełnione przed uruchomieniem zadania, jeśli Job
element jest cykliczny lub wyzwalacze, które spowodują uruchomienie zadania. Jako minimum Job
musi mieć tag (unikatowy ciąg, który identyfikuje zadanie w FirebaseJobDispatcher
obiekcie ) i typ JobService
, który powinien zostać uruchomiony. Dyspozytor zadań Firebase utworzy wystąpienie JobService
, gdy jest czas uruchamiania zadania. Element A Job
jest tworzony przy użyciu wystąpienia Firebase.JobDispatcher.Job.JobBuilder
klasy .
Poniższy fragment kodu to najprostszy przykład tworzenia Job
powiązania platformy Xamarin.Android:
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.Build();
Spowoduje to Job.Builder
przeprowadzenie pewnych podstawowych kontroli poprawności dla wartości wejściowych zadania. Wyjątek zostanie zgłoszony, jeśli nie będzie możliwe Job.Builder
utworzenie elementu Job
. Spowoduje to Job.Builder
utworzenie elementu Job
z następującymi wartościami domyślnymi:
Job
Okres istnienia (jak długo zostanie zaplanowany do uruchomienia) jest tylko do momentu ponownego uruchomienia urządzenia — po ponownym uruchomieniuJob
urządzenia zostanie utracone.- Element nie
Job
jest cykliczny — zostanie uruchomiony tylko raz. - Harmonogram
Job
zostanie zaplanowany tak szybko, jak to możliwe. - Domyślną strategią ponawiania prób dla elementu
Job
jest użycie wycofywania wykładniczego (omówiono bardziej szczegółowo poniżej w sekcji Ustawianie strategii ponawiania)
Planowanie zadań
Po utworzeniu Job
elementu należy zaplanować go z parametrem FirebaseJobDispatcher
przed jego uruchomieniem. Istnieją dwie metody planowania elementu 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);
Wartość zwrócona przez FirebaseJobDispatcher.Schedule
będzie jedną z następujących wartości całkowitych:
FirebaseJobDispatcher.ScheduleResultSuccess
– PlanJob
został pomyślnie zaplanowany.FirebaseJobDispatcher.ScheduleResultUnknownError
— Wystąpił nieznany problem, który uniemożliwił zaplanowanieJob
.FirebaseJobDispatcher.ScheduleResultNoDriverAvailable
– Użyto nieprawidłowegoIDriver
IDriver
elementu lub był w jakiś sposób niedostępny.FirebaseJobDispatcher.ScheduleResultUnsupportedTrigger
– NieTrigger
było obsługiwane.FirebaseJobDispatcher.ScheduleResultBadService
— Usługa nie jest poprawnie skonfigurowana lub jest niedostępna.
Konfigurowanie zadania
Istnieje możliwość dostosowania zadania. Przykłady dostosowywania zadania obejmują następujące elementy:
- Przekazywanie parametrów do zadania — wartość A
Job
może wymagać dodatkowych wartości do wykonania swojej pracy, na przykład podczas pobierania pliku. - Ustawianie ograniczeń — może być konieczne uruchomienie zadania tylko wtedy, gdy zostaną spełnione określone warunki. Na przykład uruchom polecenie
Job
tylko wtedy, gdy urządzenie jest ładowane. - Określ, kiedy
Job
powinno zostać uruchomione — dyspozytor zadań Firebase umożliwia aplikacjom określenie czasu uruchomienia zadania. - Deklarowanie strategii ponawiania prób dla zadań zakończonych niepowodzeniem — strategia ponawiania prób zawiera wskazówki dotyczące
FirebaseJobDispatcher
tego, co należy zrobić zJobs
tym niepowodzeniem.
Każdy z tych tematów zostanie omówiony bardziej w poniższych sekcjach.
Przekazywanie parametrów do zadania
Parametry są przekazywane do zadania przez utworzenie przekazanego Job.Builder.SetExtras
elementu Bundle
wraz z metodą :
Bundle jobParameters = new Bundle();
jobParameters.PutInt(FibonacciCalculatorJob.FibonacciPositionKey, 25);
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetExtras(jobParameters)
.Build();
Dostęp Bundle
do obiektu jest uzyskiwany z IJobParameters.Extras
właściwości w metodzie OnStartJob
:
public override bool OnStartJob(IJobParameters jobParameters)
{
int position = jobParameters.Extras.GetInt(FibonacciPositionKey, DEFAULT_VALUE);
// rest of code omitted
}
Ustawianie ograniczeń
Ograniczenia mogą pomóc zmniejszyć koszty lub opróżnienie baterii na urządzeniu. Klasa Firebase.JobDispatcher.Constraint
definiuje te ograniczenia jako wartości całkowite:
Constraint.OnUnmeteredNetwork
— Uruchamiaj zadanie tylko wtedy, gdy urządzenie jest połączone z niemetryczną siecią. Jest to przydatne, aby uniemożliwić użytkownikowi naliczanie opłat za dane.Constraint.OnAnyNetwork
— Uruchom zadanie w dowolnej sieci, z jaką urządzenie jest połączone. Jeśli określono wartość wraz z parametremConstraint.OnUnmeteredNetwork
, ta wartość będzie mieć priorytet.Constraint.DeviceCharging
— Uruchom zadanie tylko wtedy, gdy urządzenie jest ładowane.
Ograniczenia są ustawiane przy użyciu Job.Builder.SetConstraint
metody :
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetConstraint(Constraint.DeviceCharging)
.Build();
Zawiera JobTrigger
wskazówki dotyczące systemu operacyjnego o tym, kiedy zadanie powinno zostać uruchomione. Element JobTrigger
ma okno wykonywania, które definiuje zaplanowany czas uruchamiania Job
. Okno wykonywania ma wartość okna uruchamiania i wartość okna końcowego. Okno uruchamiania to liczba sekund oczekiwania urządzenia przed uruchomieniem zadania, a wartość okna końcowego to maksymalna liczba sekund oczekiwania przed uruchomieniem Job
.
Element JobTrigger
można utworzyć za Firebase.Jobdispatcher.Trigger.ExecutionWindow
pomocą metody . Na przykład Trigger.ExecutionWindow(15,60)
oznacza, że zadanie powinno działać z zakresu od 15 do 60 sekund od momentu zaplanowanego. Metoda Job.Builder.SetTrigger
jest używana do
JobTrigger myTrigger = Trigger.ExecutionWindow(15,60);
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetTrigger(myTrigger)
.Build();
Wartość domyślna JobTrigger
zadania jest reprezentowana przez wartość Trigger.Now
, która określa, że zadanie jest uruchamiane tak szybko, jak to możliwe po zaplanowaniu.
Ustawianie strategii ponawiania
Służy Firebase.JobDispatcher.RetryStrategy
do określania, ile opóźnienia urządzenie powinno używać przed próbą ponownego uruchomienia zadania, które zakończyło się niepowodzeniem. Element RetryStrategy
ma zasady, które określają, jaki algorytm bazy czasowej będzie używany do ponownego planowania zadania, które zakończyło się niepowodzeniem, oraz okno wykonywania określające okno, w którym zadanie powinno zostać zaplanowane. To okno zmiany jest definiowane przez dwie wartości. Pierwsza wartość to liczba sekund oczekiwania przed ponownym zaplanowaniem zadania ( początkowa wartość wycofywania ), a druga liczba to maksymalna liczba sekund przed uruchomieniem zadania ( maksymalna wartość wycofywania ).
Dwa typy zasad ponawiania prób są identyfikowane przez następujące wartości int:
RetryStrategy.RetryPolicyExponential
— Zasady wycofywania wykładniczego zwiększą początkową wartość wycofywania wykładniczo po każdym niepowodzeniu. Podczas pierwszego niepowodzenia zadania biblioteka będzie czekać _initial interwał określony przed ponownym zaplanowaniem zadania — na przykład 30 sekund. Po raz drugi zadanie zakończy się niepowodzeniem, biblioteka będzie czekać co najmniej 60 sekund przed próbą uruchomienia zadania. Po trzeciej nieudanej próbie biblioteka będzie czekać 120 sekund itd. Wartość domyślnaRetryStrategy
dla biblioteki Firebase Job Dispatcher jest reprezentowanaRetryStrategy.DefaultExponential
przez obiekt . Ma początkowe wycofywanie wynoszące 30 sekund i maksymalną backoff wynoszącą 3600 sekund.RetryStrategy.RetryPolicyLinear
— Ta strategia jest liniowym wycofywaniem, które powinno zostać ponownie zaplanowane, aby zadanie było uruchamiane w ustalonych odstępach czasu (dopóki nie powiedzie się). Wycofywanie liniowe najlepiej nadaje się do pracy, która musi zostać ukończona tak szybko, jak to możliwe lub w przypadku problemów, które szybko się rozwiążą. Biblioteka dyspozytora zadań programu Firebase definiujeRetryStrategy.DefaultLinear
bibliotekę, która ma okno ponownego trwania co najmniej 30 sekund i maksymalnie 3600 sekund.
Istnieje możliwość zdefiniowania niestandardowego RetryStrategy
przy użyciu FirebaseJobDispatcher.NewRetryStrategy
metody . Przyjmuje trzy parametry:
int policy
— Zasada jest jedną z poprzednichRetryStrategy
wartości,RetryStrategy.RetryPolicyLinear
, lubRetryStrategy.RetryPolicyExponential
.int initialBackoffSeconds
— Początkowe wycofywanie jest opóźnieniem w sekundach, które jest wymagane przed ponownym uruchomieniem zadania. Wartość domyślna dla tej wartości to 30 sekund.int maximumBackoffSeconds
— Maksymalna wartość wycofywania deklaruje maksymalną liczbę sekund opóźnienia przed ponownym uruchomieniem zadania. Wartość domyślna to 3600 sekund.
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();
Anulowanie zadania
Istnieje możliwość anulowania wszystkich zaplanowanych zadań lub tylko jednego zadania przy użyciu FirebaseJobDispatcher.CancelAll()
metody lub FirebaseJobDispatcher.Cancel(string)
metody:
int cancelResult = dispatcher.CancelAll();
// to cancel a single job:
int cancelResult = dispatcher.Cancel("unique-tag-for-job");
Każda z metod zwróci wartość całkowitą:
FirebaseJobDispatcher.CancelResultSuccess
— Zadanie zostało pomyślnie anulowane.FirebaseJobDispatcher.CancelResultUnknownError
— Błąd uniemożliwiał anulowanie zadania.FirebaseJobDispatcher.CancelResult.NoDriverAvailable
— NieFirebaseJobDispatcher
można anulować zadania, ponieważ nie ma prawidłowejIDriver
dostępności.
Podsumowanie
W tym przewodniku omówiono sposób użycia dyspozytora zadań Firebase do inteligentnego wykonywania pracy w tle. Omówiono w nim sposób hermetyzacji pracy, która ma być wykonywana jako element JobService
i jak używać FirebaseJobDispatcher
elementu do planowania tej pracy, określając kryteria za pomocą elementu JobTrigger
oraz sposób obsługi błędów za pomocą elementu RetryStrategy
.