WorkManager を使用すると、複数依存タスクの指定と実行順序の定義を行う処理チェーンを作成し、キューに登録できます。この機能は、複数のタスクを特定の順序で実行する必要がある場合に特に便利です。
処理チェーンを作成するには、それぞれ WorkContinuation
のインスタンスを返す WorkManager.beginWith(OneTimeWorkRequest)
または WorkManager.beginWith(List<OneTimeWorkRequest>)
を使用します。
さらに WorkContinuation
を使用し、then(OneTimeWorkRequest)
または then(List<OneTimeWorkRequest>)
を呼び出すと、依存関係にある OneTimeWorkRequest
インスタンスを追加できます。
WorkContinuation.then(...)
は、呼び出されるたびに新しい WorkContinuation
のインスタンスを返します。OneTimeWorkRequest
インスタンスの List
を追加すると、これらのリクエストを並行して実行できる可能性があります。
最後に、WorkContinuation.enqueue()
メソッドを使用して、WorkContinuation
のチェーンに対して enqueue()
を実行します。
次のような例を考えてみましょう。この例では、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
インスタンスを連結すると、親の処理リクエストの出力が子への入力として渡されます。したがって、上の例では、plantName1
、plantName2
、plantName3
の出力が cache
リクエストへの入力として渡されています。
WorkManager では、複数の親の処理リクエストからの入力を管理するために InputMerger
が使用されます。
WorkManager が提供する InputMerger
には次の 2 種類があります。
OverwritingInputMerger
: あらゆる入力のすべてのキーを出力に追加します。競合が発生すると、以前に設定したキーは上書きされます。ArrayCreatingInputMerger
: 入力をマージして、必要に応じて配列を作成します。
より具体的なユースケースがある場合は、InputMerger
をサブクラス化することで、独自の入力マージツールを作成できます。
OverwritingInputMerger
OverwritingInputMerger
は、デフォルトのマージメソッドです。マージ中にキーの競合が発生すると、キーの最新値により、結果の出力データ内の以前のバージョンが上書きされます。
たとえば、入力する植物名にそれぞれ個別の変数名("plantName1"
、"plantName2"
、"plantName3"
)と一致するキーがある場合、cache
ワーカーに渡されるデータには 3 つの Key-Value ペアが含まれます。
競合が発生すると、最後の出力となるワーカーが優先されて cache
に渡されます。
WorkRequest は並行して実行されるため、実行順序は保証されません。上の例では、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
は、各キーと 1 つの配列をペアにします。各キーが一意である場合、それぞれ要素を 1 つずつ持つ配列になります。
キーの競合が発生すると、同じキーに対する値は 1 つの配列にまとめられます。
チェーンの作成と処理のステータス
OneTimeWorkRequest
のチェーンは、処理が正常に完了すれば(Result.success()
を返せば)順番に実行されます。実行中に処理リクエストが失敗するかキャンセルされると、依存する処理リクエストに影響が生じます。
ある処理リクエスト チェーンで最初の OneTimeWorkRequest
がキューに登録されると、後続のすべての処理リクエストは、最初の処理リクエストが完了するまでブロックされます。
最初の処理リクエストは、キューに登録されて処理の制約をすべて満たすと開始されます。ルートの OneTimeWorkRequest
または List<OneTimeWorkRequest>
で処理が正常に完了した場合(Result.success()
を返した場合)、依存する処理リクエストの次のセットがキューに登録されます。
それぞれの処理リクエストが正常に完了している限り、チェーン内のすべての処理が完了するまで、同様にして残りの処理リクエストが処理されます。これは最もシンプルで多くの場合理想的なケースですが、エラーが発生した場合それに対処することも同様に重要です。
ワーカーが処理リクエストを処理している間にエラーが発生した場合は、定義したバックオフ ポリシーに従ってリクエストを再試行できます。チェーン内のあるリクエストを再試行するということは、そのリクエストのみを同じ入力データを使用して再試行するということです。並行して実行されている処理は影響を受けません。
カスタム再試行戦略の定義の詳細については、再試行とバックオフ ポリシーをご覧ください。
再試行ポリシーが定義されていない場合、再試行回数上限に達した場合、または OneTimeWorkRequest
が Result.failure()
を返すことが想定される状態に達した場合は、その処理リクエストとそれに依存するすべての処理リクエストが FAILED.
とマークされます。
OneTimeWorkRequest
がキャンセルされたときにも同じロジックが適用されます。依存する処理リクエストも CANCELLED
とマークされ、処理は実行されません。
処理リクエストが失敗したかキャンセルされたチェーンにさらに処理リクエストを追加すると、新たに追加された処理リクエストも FAILED
または CANCELLED
とマークされます。既存のチェーンの処理を拡張する場合は、ExistingWorkPolicy の APPEND_OR_REPLACE
をご覧ください。
処理リクエスト チェーンを作成する際は、依存する処理リクエストで再試行ポリシーを定義して、処理がタイムリーに完了するようにします。処理リクエストの失敗により、チェーンが不完全になったり、予期しない状態になったりすることがあります。
詳しくは、処理のキャンセルと中止をご覧ください。