WorkManager vous permet de créer et de mettre en file d'attente une chaîne de travail qui reprend plusieurs tâches dépendantes et définit l'ordre dans lequel elles doivent s'exécuter. Cette fonctionnalité est particulièrement utile lorsque vous devez exécuter plusieurs tâches dans un ordre précis.
Pour créer une chaîne de travail, vous pouvez utiliser WorkManager.beginWith(OneTimeWorkRequest)
ou WorkManager.beginWith(List<OneTimeWorkRequest>)
, qui renvoient chacun une instance de WorkContinuation
.
Une WorkContinuation
permet ensuite d'ajouter des instances OneTimeWorkRequest
dépendantes à l'aide de then(OneTimeWorkRequest)
ou de then(List<OneTimeWorkRequest>)
.
Chaque appel de WorkContinuation.then(...)
renvoie une nouvelle instance de WorkContinuation
. Si vous ajoutez une List
d'instances OneTimeWorkRequest
, ces requêtes peuvent éventuellement s'exécuter en parallèle.
Enfin, vous pouvez utiliser la méthode WorkContinuation.enqueue()
pour enqueue()
votre chaîne de WorkContinuation
.
Prenons un exemple. Imaginons trois tâches Worker différentes configurées pour s'exécuter (potentiellement en parallèle). Les résultats de ces Workers sont ensuite joints et transmis à une tâche de mise en cache Worker. Enfin, le résultat de cette tâche est transmis à un Worker d'importation, qui importe les résultats vers un serveur distant.
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();
Fusionneurs d'entrées
Lorsque vous associez des instances OneTimeWorkRequest
, la sortie des requêtes de travail parent est transmise en entrée aux enfants. Ainsi, dans l'exemple ci-dessus, les sorties de plantName1
, plantName2
et plantName3
seraient transmises en tant qu'entrées à la requête cache
.
Pour gérer les entrées provenant de plusieurs requêtes de travail parent, WorkManager utilise InputMerger
.
WorkManager fournit deux types d'InputMerger
différents :
OverwritingInputMerger
tente d'ajouter toutes les clés de toutes les entrées à la sortie. En cas de conflit, il remplace les clés définies précédemment.ArrayCreatingInputMerger
tente de fusionner les entrées en créant, si nécessaire, des tableaux.
En cas d'utilisation plus spécifique, vous pouvez écrire le vôtre en sous-classant InputMerger
.
OverwritingInputMerger
OverwritingInputMerger
est la méthode de fusion par défaut. En cas de conflit de clés dans la fusion, la dernière valeur d'une clé écrase toutes les versions précédentes dans les données de sortie obtenues.
Par exemple, si les entrées de la plante disposent chacune d'une clé correspondant à leurs noms de variables respectifs ("plantName1"
, "plantName2"
et "plantName3"
), les données transmises au nœud de calcul de cache
auront trois paires clé/valeur.
En cas de conflit, le dernier nœud de calcul à s'achever "gagne" et sa valeur est transmise à cache
.
Étant donné que vos requêtes de travail sont exécutées en parallèle, vous n'avez aucune garantie de l'ordre dans lequel elles s'exécutent. Dans l'exemple ci-dessus, plantName1
pourrait contenir la valeur "tulip"
ou "elm"
, en fonction de la valeur écrite en dernier. Si vous avez un risque de conflit de clés et que vous devez conserver toutes les données de sortie dans une fusion, ArrayCreatingInputMerger
peut être une meilleure option.
ArrayCreatingInputMerger
Pour l'exemple ci-dessus, il faut utiliser un ArrayCreatingInputMerger
, car nous voulons conserver les sorties de tous les nœuds de calcul des noms de plantes.
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
associe chaque clé à un tableau. Si chacune des clés est unique, vous obtenez une série de tableaux à un élément.
En cas de conflit de clés, toutes les valeurs correspondantes sont regroupées dans un tableau.
Statuts de chaînes et de tâches
Les chaînes de OneTimeWorkRequest
s'exécutent de manière séquentielle tant que leur travail se termine correctement (c'est-à-dire qu'elles renvoient un Result.success()
). Les requêtes de tâches peuvent échouer ou être annulées pendant l'exécution, ce qui a des effets en aval sur les requêtes de tâches dépendantes.
Lorsque la première requête OneTimeWorkRequest
est mise en file d'attente dans une chaîne de requêtes de tâches, toutes les requêtes suivantes sont bloquées jusqu'à ce que la première requête de tâche soit terminée.
Une fois en file d'attente et toutes les contraintes de travail satisfaites, la première requête de tâche s'exécute. Si le travail est terminé à la racine OneTimeWorkRequest
ou List<OneTimeWorkRequest>
(c'est-à-dire qu'il renvoie Result.success()
), l'ensemble de requêtes de tâches suivant est mis en file d'attente.
Tant que chaque requête de tâche se termine correctement, ce même schéma se propage dans le reste de votre chaîne de requêtes de tâches jusqu'à ce que toutes les tâches de la chaîne soient terminées. Bien que ce soit le cas le plus simple et le plus souvent privilégié, les états d'erreur sont tout aussi importants à gérer.
Lorsqu'une erreur se produit pendant qu'un nœud de calcul traite votre requête de tâche, vous pouvez la relancer en fonction d'une règle d'intervalle entre les tentatives que vous définissez. Si vous relancez une requête faisant partie d'une chaîne, seule cette requête sera relancée avec les données d'entrée qui lui sont fournies. Tout travail exécuté en parallèle ne sera pas affecté.
Pour en savoir plus sur la définition de règles de nouvelle tentative personnalisées, consultez les Règles concernant les nouvelles tentatives et l'intervalle entre les tentatives.
Si aucune règle de nouvelle tentative n'est définie, si elle est obsolète ou si vous atteignez un état dans lequel une OneTimeWorkRequest
renvoie Result.failure()
, cette requête de tâche et toutes les requêtes de tâches dépendantes sont marquées comme FAILED.
.
La même logique s'applique lorsqu'une OneTimeWorkRequest
est annulée. Toutes les requêtes de tâches dépendantes sont également marquées CANCELLED
et leur tâche n'est pas exécutée.
Notez que si vous ajoutez des requêtes de tâches supplémentaires à une chaîne ayant échoué ou ayant des requêtes de tâches annulées, votre nouvelle requête de tâche sera respectivement marquée comme FAILED
ou CANCELLED
. Si vous souhaitez étendre la tâche d'une chaîne existante, consultez APPEND_OR_REPLACE
dans l'ExistingWorkPolicy.
Lorsque vous créez des chaînes de requêtes de tâches dépendantes, celles-ci doivent définir des règles de nouvelle tentative pour garantir que la tâche est toujours terminée à temps. Les requêtes de tâches ayant échoué peuvent entraîner des chaînes incomplètes et/ou un état inattendu.
Pour en savoir plus, consultez Annuler et arrêter une tâche.