Firebase Job Dispatcher
Questa guida illustra come pianificare il lavoro in background usando la libreria Firebase Job Dispatcher di Google.
Panoramica
Uno dei modi migliori per mantenere reattiva un'applicazione Android all'utente consiste nel garantire che il lavoro complesso o a esecuzione prolungata venga eseguito in background. Tuttavia, è importante che il lavoro in background non influisca negativamente sull'esperienza dell'utente con il dispositivo.
Ad esempio, un processo in background potrebbe eseguire il polling di un sito Web ogni tre o quattro minuti per eseguire una query per le modifiche apportate a un determinato set di dati. Questo sembra benigno, tuttavia avrebbe un impatto disastroso sulla durata della batteria. L'applicazione riattiva ripetutamente il dispositivo, eleva la CPU a uno stato di alimentazione superiore, accende le radio, effettua le richieste di rete e quindi elabora i risultati. Peggiora perché il dispositivo non si spegne immediatamente e torna allo stato di inattività a basso consumo. Il lavoro in background pianificato in modo non adeguato può inavvertitamente mantenere il dispositivo in uno stato con requisiti di alimentazione non necessari ed eccessivi. Questa attività apparentemente innocente (polling di un sito Web) rende il dispositivo inutilizzabile in un periodo di tempo relativamente breve.
Android fornisce le API seguenti per facilitare l'esecuzione del lavoro in background, ma da soli non sono sufficienti per la pianificazione intelligente dei processi.
- Servizi finalità: i servizi finalità sono ideali per l'esecuzione del lavoro, ma non consentono di pianificare il lavoro.
- AlarmManager : queste API consentono solo di pianificare il lavoro, ma non consentono di eseguire effettivamente il lavoro. Inoltre, AlarmManager consente solo vincoli basati sul tempo, il che significa generare un allarme in un determinato momento o dopo un determinato periodo di tempo è trascorso.
- JobScheduler : JobSchedule è un'API ideale che funziona con il sistema operativo per pianificare i processi. Tuttavia, è disponibile solo per le app Android destinate al livello API 21 o superiore.
- Ricevitori di trasmissione: un'app Android può configurare ricevitori di trasmissione per eseguire operazioni in risposta a eventi o finalità a livello di sistema. Tuttavia, i ricevitori di trasmissione non forniscono alcun controllo su quando deve essere eseguito il processo. Inoltre, le modifiche apportate al sistema operativo Android limiteranno quando i ricevitori di trasmissione funzioneranno o i tipi di lavoro a cui possono rispondere.
Esistono due funzionalità chiave per eseguire in modo efficiente il lavoro in background (talvolta definito processo in background o processo):
- Pianificazione intelligente del lavoro : è importante che quando un'applicazione esegue il lavoro in background che lo fa come un buon cittadino. Idealmente, l'applicazione non deve richiedere l'esecuzione di un processo. L'applicazione deve invece specificare le condizioni che devono essere soddisfatte per quando il processo può essere eseguito e quindi pianificare l'esecuzione quando vengono soddisfatte le condizioni. In questo modo Android può eseguire in modo intelligente il lavoro. Ad esempio, le richieste di rete possono essere raggruppate per l'esecuzione contemporaneamente per sfruttare al massimo il sovraccarico necessario per la rete.
- Incapsulamento del lavoro : il codice per eseguire il lavoro in background deve essere incapsulato in un componente discreto che può essere eseguito indipendentemente dall'interfaccia utente e sarà relativamente facile da riprogrammare se il lavoro non viene completato per qualche motivo.
Firebase Job Dispatcher è una libreria di Google che fornisce un'API fluente per semplificare la pianificazione del lavoro in background. Deve essere la sostituzione di Google Cloud Manager. Firebase Job Dispatcher è costituito dalle API seguenti:
- È
Firebase.JobDispatcher.JobService
una classe astratta che deve essere estesa con la logica che verrà eseguita nel processo in background. - Un
Firebase.JobDispatcher.JobTrigger
oggetto dichiara quando deve essere avviato il processo. Questa operazione viene in genere espressa come intervallo di tempo, ad esempio, attendere almeno 30 secondi prima di avviare il processo, ma eseguire il processo entro 5 minuti. - Contiene
Firebase.JobDispatcher.RetryStrategy
informazioni sulle operazioni da eseguire quando un processo non riesce a essere eseguito correttamente. La strategia di ripetizione dei tentativi specifica il tempo di attesa prima di provare a eseguire di nuovo il processo. - Un
Firebase.JobDispatcher.Constraint
è un valore facoltativo che descrive una condizione che deve essere soddisfatta prima che il processo possa essere eseguito, ad esempio il dispositivo si trova in una rete non misurata o carica. Firebase.JobDispatcher.Job
è un'API che unifica le API precedenti in a un'unità di lavoro che può essere pianificata daJobDispatcher
. LaJob.Builder
classe viene usata per creare un'istanza di .Job
- Un
Firebase.JobDispatcher.JobDispatcher
usa le tre API precedenti per pianificare il lavoro con il sistema operativo e per fornire un modo per annullare i processi, se necessario.
Per pianificare il lavoro con Firebase Job Dispatcher, un'applicazione Xamarin.Android deve incapsulare il codice in un tipo che estende la JobService
classe. JobService
ha tre metodi del ciclo di vita che possono essere chiamati durante la durata del processo:
bool OnStartJob(IJobParameters parameters)
: questo metodo è la posizione in cui si verificherà il lavoro e deve essere sempre implementato. Viene eseguito sul thread principale. Questo metodo restituiràtrue
se è presente un lavoro rimanente ofalse
se il lavoro viene eseguito.bool OnStopJob(IJobParameters parameters)
: viene chiamato quando il processo viene arrestato per qualche motivo. Deve restituiretrue
se il processo deve essere riprogrammato per un secondo momento.JobFinished(IJobParameters parameters, bool needsReschedule)
: questo metodo viene chiamato al termine diJobService
qualsiasi operazione asincrona.
Per pianificare un processo, l'applicazione creerà un'istanza di un JobDispatcher
oggetto . Viene quindi usato un Job.Builder
oggetto per creare un Job
oggetto , fornito all'oggetto JobDispatcher
che tenterà di pianificare l'esecuzione del processo.
Questa guida illustra come aggiungere Firebase Job Dispatcher a un'applicazione Xamarin.Android e usarla per pianificare il lavoro in background.
Requisiti
Il dispatcher del processo Firebase richiede il livello API Android 9 o superiore. La libreria Firebase Job Dispatcher si basa su alcuni componenti forniti da Google Play Services; Il dispositivo deve avere Google Play Services installato.
Uso della libreria del dispatcher del processo Firebase in Xamarin.Android
Per iniziare a usare Firebase Job Dispatcher, aggiungere prima di tutto il pacchetto NuGet Xamarin.Firebase.JobDispatcher al progetto Xamarin.Android. Cercare nel Gestione pacchetti NuGet il pacchetto Xamarin.Firebase.JobDispatcher (ancora in versione non definitive).
Dopo aver aggiunto la libreria Firebase Job Dispatcher, creare una JobService
classe e quindi pianificarla per l'esecuzione con un'istanza FirebaseJobDispatcher
di .
Creazione di un processoServizio
Tutte le operazioni eseguite dalla libreria Firebase Job Dispatcher devono essere eseguite in un tipo che estende la Firebase.JobDispatcher.JobService
classe astratta. La creazione di un JobService
oggetto è molto simile alla creazione di un Service
con il framework Android:
- Estendere la
JobService
classe - Decorare la sottoclasse con .
ServiceAttribute
Sebbene non sia strettamente richiesto, è consigliabile impostare in modo esplicito ilName
parametro per facilitare il debug diJobService
. - Aggiungere un
IntentFilter
oggetto per dichiarareJobService
nella AndroidManifest.xml. Ciò consentirà anche alla libreria Firebase Job Dispatcher di individuare e richiamare .JobService
Il codice seguente è un esempio del più semplice JobService
per un'applicazione, usando il TPL per eseguire in modo asincrono alcune operazioni:
[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;
}
}
Creazione di un firebaseJobDispatcher
Prima di poter pianificare qualsiasi lavoro, è necessario creare un Firebase.JobDispatcher.FirebaseJobDispatcher
oggetto . è FirebaseJobDispatcher
responsabile della pianificazione di un oggetto JobService
. Il frammento di codice seguente è un modo per creare un'istanza FirebaseJobDispatcher
di :
// This is the "Java" way to create a FirebaseJobDispatcher object
IDriver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);
Nel frammento di codice precedente, la GooglePlayDriver
classe è che consente di FirebaseJobDispatcher
interagire con alcune delle API di pianificazione in Google Play Services nel dispositivo. Il parametro context
è qualsiasi android Context
, ad esempio un'attività. GooglePlayDriver
Attualmente è l'unica IDriver
implementazione nella libreria Firebase Job Dispatcher.
L'associazione Xamarin.Android per Firebase Job Dispatcher fornisce un metodo di estensione per creare un oggetto FirebaseJobDispatcher
da Context
:
FirebaseJobDispatcher dispatcher = context.CreateJobDispatcher();
Una volta creata un'istanza FirebaseJobDispatcher
di , è possibile creare ed Job
eseguire il codice nella JobService
classe . L'oggetto Job
viene creato da un Job.Builder
oggetto e verrà illustrato nella sezione successiva.
Creazione di un oggetto Firebase.JobDispatcher.Job con Job.Builder
La Firebase.JobDispatcher.Job
classe è responsabile dell'incapsulamento dei metadati necessari per eseguire un oggetto JobService
. UnJob
oggetto contiene informazioni come qualsiasi vincolo che deve essere soddisfatto prima che il processo possa essere eseguito, se è Job
ricorrente o qualsiasi trigger che causerà l'esecuzione del processo. Come minimo, un Job
oggetto deve avere un tag (una stringa univoca che identifica il processo in FirebaseJobDispatcher
) e il tipo di JobService
che deve essere eseguito. Il dispatcher del processo Firebase crea un'istanza di JobService
quando è il momento di eseguire il processo. Un Job
oggetto viene creato utilizzando un'istanza della Firebase.JobDispatcher.Job.JobBuilder
classe .
Il frammento di codice seguente è l'esempio più semplice di come creare un Job
oggetto usando l'associazione Xamarin.Android:
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.Build();
Job.Builder
Eseguirà alcuni controlli di convalida di base sui valori di input per il processo. Se non è possibile creare un oggetto , verrà generata un'eccezione Job.Builder
Job
. Job.Builder
Verrà creato un oggetto Job
con le impostazioni predefinite seguenti:
- La durata di un
Job
oggetto (per quanto tempo verrà pianificata per l'esecuzione) è solo fino al riavvio del dispositivo, una volta che il dispositivo viene riavviatoJob
. - Un
Job
oggetto non è ricorrente: verrà eseguito una sola volta. - Verrà pianificata l'esecuzione di un
Job
oggetto il prima possibile. - La strategia di ripetizione dei tentativi predefinita per un
Job
oggetto consiste nell'usare un backoff esponenziale (descritto più dettagliatamente di seguito nella sezione Impostazione di un retryStrategy)
Programmazione di un processo
Dopo aver creato , Job
deve essere pianificato con prima dell'esecuzione FirebaseJobDispatcher
. Per la pianificazione di un oggetto Job
sono disponibili due metodi:
// 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);
Il valore restituito da FirebaseJobDispatcher.Schedule
sarà uno dei valori integer seguenti:
FirebaseJobDispatcher.ScheduleResultSuccess
– L'oggettoJob
è stato pianificato correttamente.FirebaseJobDispatcher.ScheduleResultUnknownError
– Si è verificato un problema sconosciuto che impediva la pianificazione dell'oggettoJob
.FirebaseJobDispatcher.ScheduleResultNoDriverAvailable
- È stato usato un valore non validoIDriver
o nonIDriver
era in qualche modo disponibile.FirebaseJobDispatcher.ScheduleResultUnsupportedTrigger
: l'oggettoTrigger
non è supportato.FirebaseJobDispatcher.ScheduleResultBadService
: il servizio non è configurato correttamente o non è disponibile.
Configurazione di un processo
È possibile personalizzare un processo. Di seguito sono riportati alcuni esempi di personalizzazione di un processo:
- Passaggio di parametri a un processo : un
Job
oggetto può richiedere valori aggiuntivi per eseguire il proprio lavoro, ad esempio il download di un file. - Set Constraints (Imposta vincoli ): potrebbe essere necessario eseguire un processo solo quando vengono soddisfatte determinate condizioni. Ad esempio, eseguire un
Job
oggetto solo quando il dispositivo viene ricaricato. - Specificare quando
Job
deve essere eseguito : il dispatcher del processo Firebase consente alle applicazioni di specificare un'ora in cui deve essere eseguito il processo. - Dichiarare una strategia di ripetizione dei tentativi per i processi non riusciti: una strategia di ripetizione dei tentativi fornisce indicazioni sulle
FirebaseJobDispatcher
operazioni da eseguire conJobs
questo errore.
Ognuno di questi argomenti verrà illustrato più in dettaglio nelle sezioni seguenti.
Passaggio di parametri a un processo
I parametri vengono passati a un processo creando un Bundle
oggetto passato insieme al Job.Builder.SetExtras
metodo :
Bundle jobParameters = new Bundle();
jobParameters.PutInt(FibonacciCalculatorJob.FibonacciPositionKey, 25);
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetExtras(jobParameters)
.Build();
L'oggetto Bundle
IJobParameters.Extras
è accessibile dalla proprietà nel OnStartJob
metodo :
public override bool OnStartJob(IJobParameters jobParameters)
{
int position = jobParameters.Extras.GetInt(FibonacciPositionKey, DEFAULT_VALUE);
// rest of code omitted
}
Impostazione dei vincoli
I vincoli consentono di ridurre i costi o lo scaricamento della batteria nel dispositivo. La Firebase.JobDispatcher.Constraint
classe definisce questi vincoli come valori interi:
Constraint.OnUnmeteredNetwork
: eseguire il processo solo quando il dispositivo è connesso a una rete senza parametri. Ciò è utile per impedire all'utente di incorrere in addebiti per i dati.Constraint.OnAnyNetwork
: eseguire il processo in qualsiasi rete a cui è connesso il dispositivo. Se specificato insiemeConstraint.OnUnmeteredNetwork
a , questo valore avrà la priorità.Constraint.DeviceCharging
: eseguire il processo solo quando il dispositivo viene ricaricato.
I vincoli vengono impostati con il Job.Builder.SetConstraint
metodo :
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetConstraint(Constraint.DeviceCharging)
.Build();
JobTrigger
Fornisce indicazioni al sistema operativo relativo all'avvio del processo. Un JobTrigger
oggetto ha una finestra in esecuzione che definisce un'ora pianificata per l'esecuzione dell'oggetto Job
. La finestra di esecuzione ha un valore della finestra iniziale e un valore della finestra finale. La finestra iniziale è il numero di secondi di attesa del dispositivo prima di eseguire il processo e il valore della finestra finale è il numero massimo di secondi di attesa prima di eseguire .Job
È possibile creare un oggetto JobTrigger
con il Firebase.Jobdispatcher.Trigger.ExecutionWindow
metodo . Ad esempio Trigger.ExecutionWindow(15,60)
, significa che il processo deve essere eseguito tra 15 e 60 secondi da quando è pianificato. Il Job.Builder.SetTrigger
metodo viene usato per
JobTrigger myTrigger = Trigger.ExecutionWindow(15,60);
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetTrigger(myTrigger)
.Build();
Il valore predefinito JobTrigger
per un processo è rappresentato dal valore Trigger.Now
, che specifica che un processo deve essere eseguito il prima possibile dopo la pianificazione.
Impostazione di un retryStrategy
Viene Firebase.JobDispatcher.RetryStrategy
usato per specificare la quantità di ritardo che un dispositivo deve usare prima di provare a eseguire nuovamente un processo non riuscito. Un RetryStrategy
oggetto dispone di un criterio, che definisce l'algoritmo di base temporale che verrà usato per pianificare nuovamente il processo non riuscito e una finestra di esecuzione che specifica una finestra in cui deve essere pianificato il processo. Questa finestra di riprogrammazione è definita da due valori. Il primo valore è il numero di secondi di attesa prima di riprogrammare il processo (il valore di backoff iniziale) e il secondo numero è il numero massimo di secondi prima che il processo debba essere eseguito (il valore di backoff massimo).
I due tipi di criteri di ripetizione dei tentativi sono identificati da questi valori int:
RetryStrategy.RetryPolicyExponential
: un criterio di backoff esponenziale aumenterà il valore di backoff iniziale in modo esponenziale dopo ogni errore. La prima volta che un processo ha esito negativo, la libreria attenderà l'intervallo di _initial specificato prima di riprogrammare il processo, ad esempio 30 secondi. La seconda volta che il processo ha esito negativo, la libreria attenderà almeno 60 secondi prima di provare a eseguire il processo. Dopo il terzo tentativo non riuscito, la libreria attenderà 120 secondi e così via. Il valore predefinitoRetryStrategy
per la libreria Firebase Job Dispatcher è rappresentato dall'oggettoRetryStrategy.DefaultExponential
. Ha un backoff iniziale di 30 secondi e un backoff massimo di 3600 secondi.RetryStrategy.RetryPolicyLinear
: questa strategia è un backoff lineare che il processo deve essere riprogrammato per l'esecuzione a intervalli impostati (fino a quando non riesce). Il backoff lineare è più adatto per il lavoro che deve essere completato il prima possibile o per i problemi che si risolvono rapidamente. La libreria Firebase Job Dispatcher definisce un oggettoRetryStrategy.DefaultLinear
con una finestra di riprogrammazione di almeno 30 secondi e fino a 3600 secondi.
È possibile definire un oggetto personalizzato RetryStrategy
con il FirebaseJobDispatcher.NewRetryStrategy
metodo . Accetta tre parametri:
int policy
: il criterio è uno dei valori precedentiRetryStrategy
,RetryStrategy.RetryPolicyLinear
oRetryStrategy.RetryPolicyExponential
.int initialBackoffSeconds
: il backoff iniziale è un ritardo, in secondi, necessario prima di provare a eseguire di nuovo il processo. Il valore predefinito per questo è 30 secondi.int maximumBackoffSeconds
: il valore di backoff massimo dichiara il numero massimo di secondi di ritardo prima di tentare di eseguire di nuovo il processo. Il valore predefinito è 3600 secondi.
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();
Annullamento di un processo
È possibile annullare tutti i processi pianificati o solo un singolo processo usando il FirebaseJobDispatcher.CancelAll()
metodo o il FirebaseJobDispatcher.Cancel(string)
metodo :
int cancelResult = dispatcher.CancelAll();
// to cancel a single job:
int cancelResult = dispatcher.Cancel("unique-tag-for-job");
Uno dei due metodi restituirà un valore intero:
FirebaseJobDispatcher.CancelResultSuccess
– Il processo è stato annullato correttamente.FirebaseJobDispatcher.CancelResultUnknownError
: un errore ha impedito l'annullamento del processo.FirebaseJobDispatcher.CancelResult.NoDriverAvailable
FirebaseJobDispatcher
: non è possibile annullare il processo perché non è disponibile alcun valore validoIDriver
.
Riepilogo
Questa guida ha illustrato come usare Firebase Job Dispatcher per eseguire in modo intelligente il lavoro in background. Ha illustrato come incapsulare il lavoro da eseguire come e JobService
come usare FirebaseJobDispatcher
per pianificare il lavoro, specificando i criteri con un JobTrigger
e come gestire gli errori con un oggetto RetryStrategy
.