將工作鏈結在一起

WorkManager 可讓您建立工作鏈結並排入佇列;這個工作鏈結可指定多個相依工作並定義其執行順序。如果您需要依特定順序執行多項工作,這項功能非常實用。

如要建立工作鏈結,您可以使用 WorkManager.beginWith(OneTimeWorkRequest)WorkManager.beginWith(List<OneTimeWorkRequest>),每個事件都會傳回 WorkContinuation 的執行個體。

接著,WorkContinuation 可用來新增採用 then(OneTimeWorkRequest)then(List<OneTimeWorkRequest>) 的相依 OneTimeWorkRequest 執行個體。

每次叫用 WorkContinuation.then(...) 都會傳回 WorkContinuation 的「新」執行個體。如果新增 OneTimeWorkRequest 執行個體的 List,這些要求可能會同時執行。

最後,您可以使用 WorkContinuation.enqueue() 方法來 enqueue() 您的 WorkContinuation 鏈結。

讓我們來看看下面這個例子。在這個範例中,3 個不同的工作站工作都設定為執行 (可能同時)。然後,系統會彙整這些工作站的結果,並傳遞至快取工作站工作。最後,該工作的輸出內容會傳遞至上傳工作站,以便將結果上傳至遠端伺服器。

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();

輸入合併

鏈結 OneTimeWorkRequest 執行個體時,系統會傳入父項工作要求的輸出內容當做子項的輸入內容。因此,在上述範例中,plantName1plantName2plantName3 的輸出內容會傳入並當做 cache 要求的輸入內容。

為了管理多個父項工作要求的輸入內容,WorkManager 會使用 InputMerger

WorkManager 提供兩種不同類型的 InputMerger

如果您有更具體的用途,可以將 InputMerger 設為子類別,自行編寫用途。

OverwritingInputMerger

OverwritingInputMerger 是預設的合併方法。如果合併方法中發生鍵衝突,鍵的最新值將會覆寫所產生的輸出內容資料中的先前版本。

舉例來說,如果每個植物輸入內容的鍵符合各自的變數名稱 ("plantName1""plantName2""plantName3"),則傳遞至 cache 工作站的資料會具備三個鍵/值組合。

這張圖表顯示三個工作,分別傳遞不同的輸出內容到鏈結中的下一個工作。由於這三個輸出內容都有不同的鍵,因此下一個工作會收到三個鍵/值組合。

如有衝突,則最後一個完成的工作站「勝出」,而其值會傳遞至 cache

這張圖表顯示三個工作,分別傳遞輸出內容到鏈結中的下一個工作。在這種情況下,其中兩個工作會使用同一個鍵產生輸出內容。因此,下一個工作會收到兩個鍵/值組合,其中一個相衝突的輸出內容會遭到捨棄。

由於工作要求是同時執行,因此無法保證其執行順序。在上述範例中,視最後寫入的值而定,plantName1 可保留 "tulip""elm" 的值。如果您可能遇到鍵衝突,而且需要在合併方法中保留所有輸出內容資料,選擇 ArrayCreatingInputMerger 可能更適合。

ArrayCreatingInputMerger

針對上述範例,假設我們要保留所有植物名稱工作站的輸出內容,則應使用 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 會將每個鍵與陣列配對。如果每個鍵都不重複,即代表您的結果是一系列單一元素陣列。

這張圖表顯示三個工作,分別傳遞不同的輸出內容到鏈結中的下一個工作。下一個工作會收到三個陣列,每個輸出內容的鍵各有一個陣列。每個陣列都包含一個成員。

如發生任何鍵衝突,系統會將所有對應值合併在一個陣列中。

這張圖表顯示三個工作,分別傳遞輸出內容到鏈結中的下一個工作。在這種情況下,其中兩個工作會使用同一個鍵產生輸出內容。下一個工作會收到兩個陣列,每個鍵各一個。其中一個陣列會有兩個成員,因為有兩個輸出內容包含該鍵。

鏈結和工作狀態

只要工作成功完成,OneTimeWorkRequest 的鏈結就會依序執行 (也就是傳回 Result.success())。工作要求可能會在執行期間失敗或遭到取消,連帶影響到後續的相依工作要求。

當第一個 OneTimeWorkRequest 排入工作要求的鏈結中,所有後續的工作要求都會遭到封鎖,直到第一個工作要求完成為止。

顯示工作鏈結的圖表。第一個工作已排入佇列;所有後續工作都會遭到封鎖,直到第一個工作完成為止。

一旦排入佇列且符合所有工作限制後,第一個工作要求就會開始執行。如果工作在根 OneTimeWorkRequestList<OneTimeWorkRequest> 中順利完成 (也就是傳回 Result.success()),系統就會將下一組相依工作要求排入佇列。

顯示工作鏈結的圖表。第一項工作已順利完成,且後續的兩項工作也排入佇列。其餘工作會因為先前的工作遭到封鎖。

只要每個工作要求都順利完成,相同的模式就會在其他工作要求鏈結如法炮製,直到鏈結中的所有工作都完成為止。雖然這是最簡單且經常偏好使用的情況,但錯誤狀態同樣必須處理。

如果工作站在處理工作要求時發生錯誤,可以按照您定義的輪詢政策重試該要求。重試鏈結內的要求時,系統只會以要求中提供的輸入內容資料重試要求。但所有同時執行的作業都不會受到影響。

顯示工作鏈結的圖表。其中一個工作失敗,但已定義輪詢政策。系統會在經過適當的時間後,再次執行該項工作。鏈結中的後續工作都會遭到封鎖,直到該項工作成功執行為止。

如要進一步瞭解如何定義自訂重試策略,請參閱重試和輪詢政策

如果該重試政策未定義或用盡,或者到達 OneTimeWorkRequest 傳回 Result.failure() 的特定狀態,系統就會將該工作要求和所有相依工作要求標示為 FAILED.

顯示工作鏈結的圖表。1 項工作已失敗,無法重試。因此,在鏈結中的後續所有工作也會失敗。

OneTimeWorkRequest 遭到取消時也適用同樣的邏輯。所有相依工作要求都會標示為 CANCELLED,系統不會執行其工作。

顯示工作鏈結的圖表。1 項工作已取消。因此,在鏈結中的後續所有工作都會取消。

請注意,如果您要在鏈結已失敗或已取消工作要求時附加更多工作要求,那麼新附加的工作要求也會分別標示為 FAILEDCANCELLED。如要擴充現有鏈結的工作,請參閱 ExistingWorkPolicy 中的 APPEND_OR_REPLACE 一節。

建立工作要求鏈結時,相依工作要求應定義重試政策,以確保工作一定會及時完成。失敗的工作要求可能會導致鏈結不完整和/或非預期的狀態。

詳情請參閱取消及停止工作