Condividi tramite


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):

  1. 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.
  2. 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 da JobDispatcher. La Job.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 o false se il lavoro viene eseguito.
  • bool OnStopJob(IJobParameters parameters) : viene chiamato quando il processo viene arrestato per qualche motivo. Deve restituire true se il processo deve essere riprogrammato per un secondo momento.
  • JobFinished(IJobParameters parameters, bool needsReschedule) : questo metodo viene chiamato al termine di JobService 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 FirebaseJobDispatcherdi .

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:

  1. Estendere la JobService classe
  2. Decorare la sottoclasse con .ServiceAttribute Sebbene non sia strettamente richiesto, è consigliabile impostare in modo esplicito il Name parametro per facilitare il debug di JobService.
  3. Aggiungere un IntentFilter oggetto per dichiarare JobService 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 FirebaseJobDispatcherdi :

// 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.BuilderJob. Job.Builder Verrà creato un oggetto Job con le impostazioni predefinite seguenti:

  • La durata di un Joboggetto (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 , Jobdeve essere pianificato con prima dell'esecuzione FirebaseJobDispatcher . Per la pianificazione di un oggetto Jobsono 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'oggetto Job è stato pianificato correttamente.
  • FirebaseJobDispatcher.ScheduleResultUnknownError – Si è verificato un problema sconosciuto che impediva la pianificazione dell'oggetto Job .
  • FirebaseJobDispatcher.ScheduleResultNoDriverAvailable - È stato usato un valore non valido IDriver o non IDriver era in qualche modo disponibile.
  • FirebaseJobDispatcher.ScheduleResultUnsupportedTrigger : l'oggetto Trigger 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:

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 BundleIJobParameters.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 insieme Constraint.OnUnmeteredNetworka , 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 predefinito RetryStrategy per la libreria Firebase Job Dispatcher è rappresentato dall'oggetto RetryStrategy.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 oggetto RetryStrategy.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:

  1. int policy : il criterio è uno dei valori precedenti RetryStrategy , RetryStrategy.RetryPolicyLinearo RetryStrategy.RetryPolicyExponential.
  2. 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.
  3. 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.NoDriverAvailableFirebaseJobDispatcher: 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.