Concatenamento dei lavori

WorkManager ti consente di creare e mettere in coda una catena di lavoro che specifica più attività dipendenti e definisce l'ordine in cui devono essere eseguite. Questa funzionalità è particolarmente utile quando devi eseguire diverse attività in un ordine specifico.

Per creare una catena di lavoro, puoi utilizzare WorkManager.beginWith(OneTimeWorkRequest) o WorkManager.beginWith(List<OneTimeWorkRequest>) , che restituiscono ciascuno un'istanza di WorkContinuation.

Un WorkContinuation può quindi essere utilizzato per aggiungere istanze OneTimeWorkRequest dipendenti utilizzando then(OneTimeWorkRequest) o then(List<OneTimeWorkRequest>).

Ogni chiamata di WorkContinuation.then(...) restituisce una nuova istanza di WorkContinuation. Se aggiungi un List di OneTimeWorkRequest istanze, queste richieste possono potenzialmente essere eseguite in parallelo.

Infine, puoi utilizzare il metodo WorkContinuation.enqueue() per enqueue() la tua catena di WorkContinuation.

Vediamo un esempio. In questo esempio, sono configurati per l'esecuzione (potenzialmente in parallelo) 3 diversi job worker. I risultati di questi worker vengono unificati e trasmessi a un job worker di memorizzazione nella cache. Infine, l'output di questo job viene passato a un worker di caricamento, che carica i risultati su un server remoto.

Kotlin

WorkManager.getInstance(myContext)
   // Candidates to run in parallel
   .beginWith(listOf(plantName1, plantName2, plantName3))
   // Dependent work (only runs after all previous work in chain)
   .then(cache)
   .then(upload)
   // Call enqueue to kick things off
   .enqueue()

Java

WorkManager.getInstance(myContext)
   // Candidates to run in parallel
   .beginWith(Arrays.asList(plantName1, plantName2, plantName3))
   // Dependent work (only runs after all previous work in chain)
   .then(cache)
   .then(upload)
   // Call enqueue to kick things off
   .enqueue();

Unioni di input

Quando concateni le istanze OneTimeWorkRequest, l'output delle richieste di lavoro principali viene passato come input alle istanze secondarie. Quindi, nell'esempio precedente, gli output di plantName1, plantName2 e plantName3 verranno passati come input alla richiesta cache.

Per gestire gli input di più richieste di lavoro principali, WorkManager utilizza InputMerger.

Esistono due tipi diversi di InputMerger forniti da WorkManager:

  • OverwritingInputMerger tenta di aggiungere all'output tutte le chiavi di tutti gli input. In caso di conflitti, sovrascrive le chiavi impostate in precedenza.

  • ArrayCreatingInputMerger tenta di unire gli input, creando array quando necessario.

Se hai un caso d'uso più specifico, puoi scrivere il tuo eseguendo la sottoclasse InputMerger.

OverwritingInputMerger

OverwritingInputMerger è il metodo di unione predefinito. Se si verificano conflitti tra le chiavi durante l'unione, l'ultimo valore di una chiave sovrascriverà le versioni precedenti nei dati di output risultanti.

Ad esempio, se ogni input della pianta ha una chiave corrispondente al rispettivo nome della variabile ("plantName1", "plantName2" e "plantName3"), i dati passati al worker cache avranno tre coppie chiave-valore.

Diagramma che mostra tre job che passano output diversi al job successivo nella catena. Poiché i tre output hanno chiavi diverse, il job successivo riceve tre coppie chiave/valore.

In caso di conflitto, l'ultimo worker a completare l'operazione "vince" e il suo valore viene passato a cache.

Diagramma che mostra tre job che passano gli output al job successivo nella catena. In questo caso, due di questi job producono output con la stessa chiave. Di conseguenza, il job successivo riceve due coppie chiave/valore, con uno degli output in conflitto eliminato.

Poiché le richieste di lavoro vengono eseguite in parallelo, non hai garanzie per l'ordine di esecuzione. Nell'esempio precedente, plantName1 potrebbe contenere un valore pari a "tulip" o "elm", a seconda di quale valore viene scritto per ultimo. Se hai la possibilità di un conflitto di chiavi e devi conservare tutti i dati di output in un'unione, ArrayCreatingInputMerger potrebbe essere un'opzione migliore.

ArrayCreatingInputMerger

Per l'esempio precedente, dato che vogliamo conservare gli output di tutti i worker con nome pianta, dobbiamo utilizzare un ArrayCreatingInputMerger.

Kotlin

val cache: OneTimeWorkRequest = OneTimeWorkRequestBuilder<PlantWorker>()
   .setInputMerger(ArrayCreatingInputMerger::class)
   .setConstraints(constraints)
   .build()

Java

OneTimeWorkRequest cache = new OneTimeWorkRequest.Builder(PlantWorker.class)
       .setInputMerger(ArrayCreatingInputMerger.class)
       .setConstraints(constraints)
       .build();

ArrayCreatingInputMerger associa ogni chiave a un array. Se ogni chiave è univoca, il risultato è una serie di array con un solo elemento.

Diagramma che mostra tre job che passano output diversi al job successivo nella catena. Il job successivo riceve tre array, uno per ciascuna delle chiavi di output. Ogni array ha un solo membro.

Se si verificano collisioni di chiavi, i valori corrispondenti vengono raggruppati in un array.

Diagramma che mostra tre job che passano gli output al job successivo nella catena. In questo caso, due di questi job producono output con la stessa chiave. Il job successivo riceve due array, uno per ogni chiave. Uno di questi array ha due membri, poiché c&#39;erano due output con quella chiave.

Concatenamento e stati di lavoro

Le catene di OneTimeWorkRequest vengono eseguite in sequenza finché il loro lavoro non viene completato correttamente (ovvero restituiscono un Result.success()). Le richieste di lavoro potrebbero non riuscire o essere annullate durante l'esecuzione, il che ha effetti a valle sulle richieste di lavoro dipendenti.

Quando la prima OneTimeWorkRequest viene inserita in coda in una catena di richieste di lavoro, tutte le richieste di lavoro successive vengono bloccate finché il lavoro della prima richiesta di lavoro non viene completato.

Diagramma che mostra una catena di job. Il primo job viene messo in coda; tutti i job successivi vengono bloccati finché il primo non viene completato.

Una volta accodata e soddisfatte tutte le limitazioni del lavoro, inizia l'esecuzione della prima richiesta di lavoro. Se il lavoro viene completato correttamente nella radice OneTimeWorkRequest o List<OneTimeWorkRequest> (ovvero restituisce un Result.success()), viene accodata la serie successiva di richieste di lavoro dipendenti.

Diagramma che mostra una catena di job. Il primo job è stato eseguito correttamente e i due successori immediati sono stati inseriti nella coda. I job rimanenti vengono bloccati fino al completamento dei job precedenti.

Finché ogni richiesta di lavoro viene completata correttamente, questo stesso pattern si propaga al resto della catena di richieste di lavoro finché tutto il lavoro nella catena non viene completato. Sebbene questo sia lo scenario più semplice e spesso preferito, è altrettanto importante gestire gli stati di errore.

Quando si verifica un errore durante l'elaborazione della richiesta di lavoro da parte di un worker, puoi riprovare a inviare la richiesta in base a un criterio di backoff che definisci. Il nuovo tentativo di una richiesta che fa parte di una catena significa che verrà riprovata solo quella richiesta con i dati di input forniti. Qualsiasi lavoro in esecuzione in parallelo non verrà interessato.

Diagramma che mostra una catena di job. Uno dei job non è riuscito, ma è stata definita una strategia di backoff. Il job verrà eseguito di nuovo dopo il periodo di tempo appropriato. I job successivi nella catena vengono bloccati finché non viene eseguito correttamente.

Per ulteriori informazioni sulla definizione di strategie di ripetizione personalizzate, consulta Criteri di ripetizione e backoff.

Se i criteri di ripetizione non sono definiti o sono esauriti oppure se raggiungi uno stato in cui OneTimeWorkRequest restituisce Result.failure(), la richiesta di lavoro e tutte le richieste di lavoro dipendenti vengono contrassegnate come FAILED..

Diagramma che mostra una catena di job. Un job non è riuscito e non può essere riprovato. Di conseguenza, anche tutti i job successivi nella catena non vanno a buon fine.

La stessa logica si applica quando un OneTimeWorkRequest viene annullato. Anche le richieste di lavoro dipendenti vengono contrassegnate con CANCELLED e il lavoro non verrà eseguito.

Diagramma che mostra una catena di job. Un job è stato annullato. Di conseguenza, vengono annullati anche tutti i job successivi nella catena.

Tieni presente che se aggiungi altre richieste di lavoro a una catena di richieste non riuscite o annullate, anche la nuova richiesta di lavoro aggiunta verrà contrassegnata come FAILED o CANCELLED, rispettivamente. Se vuoi estendere il lavoro di una catena esistente, consulta APPEND_OR_REPLACE in ExistingWorkPolicy.

Quando crei catene di richieste di lavoro, le richieste di lavoro dipendenti devono definire i criteri di ripetizione per garantire che il lavoro venga sempre completato in modo tempestivo. Le richieste di lavoro non riuscite potrebbero comportare catene incomplete e/o uno stato imprevisto.

Per saperne di più, consulta Annullare e interrompere un lavoro.