WorkManager consente di creare e accodare 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 determinato ordine.
Per creare una catena di lavoro, puoi utilizzare WorkManager.beginWith(OneTimeWorkRequest)
o WorkManager.beginWith(List<OneTimeWorkRequest>)
, che restituiscono ciascuno un'istanza di WorkContinuation
.
È quindi possibile utilizzare un WorkContinuation
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 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 3 job worker diversi (potenzialmente in parallelo). I risultati di questi worker vengono quindi uniti e passati a un job worker di memorizzazione nella cache. Infine, l'output di quel 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();
Fusioni di input
Quando concateni le istanze OneTimeWorkRequest
, l'output delle richieste di lavoro padre
viene trasmesso come input alle istanze figlio. Nell'esempio precedente, gli output di plantName1
, plantName2
e plantName3
vengono passati come input alla richiesta cache
.
Per gestire gli input da più richieste di lavoro del genitore, WorkManager utilizza InputMerger
.
WorkManager offre due diversi tipi di InputMerger
:
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 scriverlo creando sottoclassi InputMerger
.
SovrascritturaInputMerger
OverwritingInputMerger
è il metodo di unione predefinito. In caso di conflitti di chiavi nell'unione, l'ultimo valore di una chiave sovrascriverà eventuali versioni precedenti dei dati di output risultanti.
Ad esempio, se gli input dell'impianto hanno ciascuno una chiave corrispondente ai rispettivi
nomi di variabili ("plantName1"
, "plantName2"
e "plantName3"
), i dati
trasferiti al worker cache
avranno tre coppie chiave-valore.
In caso di conflitto, l'ultimo worker che completa "vince" e il suo valore viene passato a cache
.
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 "tulip"
o "elm"
, a seconda di quale valore è stato scritto per ultimo. Se esiste la possibilità che si verifichi un conflitto di chiavi e devi conservare tutti i dati di output
in una fusione, ArrayCreatingInputMerger
potrebbe essere un'opzione migliore.
ArrayCreazionediinput
Per l'esempio precedente, dato che vogliamo conservare gli output di tutti i nomi di impianto worker, dovremmo usare un'istruzione 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
accoppia ogni chiave a un array. Se ogni chiave è univoca, il risultato è una serie di array di un elemento.
In caso di conflitti di chiavi, tutti i valori corrispondenti vengono raggruppati in un array.
Concatenamento e status di lavoro
Le catene di OneTimeWorkRequest
vengono eseguite in sequenza finché il loro lavoro viene completato correttamente (ovvero, viene restituito un Result.success()
). Le richieste di lavoro potrebbero non riuscire o essere annullate durante l'esecuzione, con effetti downstream sulle richieste di lavoro dipendenti.
Quando il primo OneTimeWorkRequest
viene accodato in una catena di richieste di lavoro,
tutte le richieste di lavoro successive vengono bloccate fino al completamento di quello della prima
richiesta di lavoro.
Una volta accodati e soddisfatti tutti i vincoli di lavoro, inizia l'esecuzione della prima richiesta di lavoro. Se il lavoro viene completato correttamente nell'istanza principale
OneTimeWorkRequest
o List<OneTimeWorkRequest>
(ovvero, viene restituito un
Result.success()
), il set di richieste di lavoro dipendenti successivo verrà
in coda.
Finché ogni richiesta di lavoro viene completata correttamente, questo stesso pattern si propaga alle altre richieste della catena di lavoro fino al completamento di tutto il lavoro nella catena. Sebbene questo sia il caso più semplice e spesso preferito, è altrettanto importante gestire gli stati di errore.
Quando si verifica un errore mentre un worker elabora la tua richiesta di lavoro, puoi ritentare la richiesta in base a un criterio di backoff che hai definito. Un nuovo tentativo per una richiesta che fa parte di una catena significa che verrà ritentata solo quella richiesta con i dati di input che le sono stati forniti. Qualsiasi lavoro eseguito in parallelo non sarà interessato.
Per ulteriori informazioni sulla definizione di strategie personalizzate per i nuovi tentativi, consulta Criteri per nuovi tentativi e backoff.
Se il criterio per i nuovi tentativi non è definito o è esaurito, oppure se raggiungi uno stato in cui OneTimeWorkRequest
restituisce Result.failure()
, questa richiesta di lavoro e tutte le richieste di lavoro dipendenti vengono contrassegnate come FAILED.
.
La stessa logica si applica quando un OneTimeWorkRequest
viene annullato. Anche tutte le richieste di lavoro dipendenti sono contrassegnate con CANCELLED
e il loro lavoro non verrà eseguito.
Tieni presente che se aggiungi altre richieste di lavoro a una catena che non è riuscita o ha annullato richieste di lavoro, anche la richiesta di lavoro appena aggiunta verrà contrassegnata rispettivamente con FAILED
o CANCELLED
. Se vuoi estendere il funzionamento di una catena esistente, consulta APPEND_OR_REPLACE
in
existingWorkPolicy.
Quando si creano catene di richieste di lavoro, le richieste di lavoro dipendenti devono definire criteri di ripetizione per garantire che il lavoro venga sempre completato in modo tempestivo. Le richieste di lavoro non riuscite potrebbero causare catene incomplete e/o stati imprevisti.
Per ulteriori informazioni, consulta Annullamento e interruzione del lavoro.