複数のワーカーのチェイン方法
本連載は、Android Jetpackを紹介しています。前々回から3回にわたって、WorkManagerを紹介しています。今回は最後として、より発展的な内容を紹介します。まず、複数のワーカーを続けて実行する方法を紹介します。
なお、今回の今回のサンプルデータは、GitHubから参照できます。
ワーカーを繋げるWorkContinuation
これまで紹介してきたWorkManagerの使い方は、ひとつのワーカーを実行して終わりというものでした。それを数珠繋ぎに実行することができます。例えば、CreateCountWorker、ReceiveCountWorker、FinishCountWorkerの3個のワーカーがあるとします。そして、CreateCountWorkerが終了したのちにReceiveCountWorkerを実行し、ReceiveCountWorkerが終了したのちにFinishCountWorkerを実行することができます(図1)。
このように、ひとつのワーカーの終了を受けて、続けて別のワーカーを実行することを、ワークチェインといいます。
ワークチェインを実行する場合、WorkManagerへのキュー登録コードが、Javaではリスト1、Kotlinではリスト2のように変わってきます。
OneTimeWorkRequest.Builder workRequestBuilder = new OneTimeWorkRequest.Builder(CreateCountWorker.class); // (1) OneTimeWorkRequest createCountWorkRequest = workRequestBuilder.build(); // (1) workRequestBuilder = new OneTimeWorkRequest.Builder(ReceiveCountWorker.class); // (2) OneTimeWorkRequest receiveCountWorkRequest = workRequestBuilder.build(); // (2) workRequestBuilder = new OneTimeWorkRequest.Builder(FinishCountWorker.class); // (3) OneTimeWorkRequest finishCountWorkRequest = workRequestBuilder.build(); // (3) WorkManager workManager = WorkManager.getInstance(MainActivity.this); // (4) WorkContinuation workContinuation = workManager.beginWith(createCountWorkRequest); // (5) workContinuation = workContinuation.then(receiveCountWorkRequest); // (6) workContinuation = workContinuation.then(finishCountWorkRequest); // (7) workContinuation.enqueue(); // (8)
var workRequestBuilder = OneTimeWorkRequestBuilder<CreateCountWorker>() // (1) val createCountWorkRequest = workRequestBuilder.build() // (1) workRequestBuilder = OneTimeWorkRequestBuilder<ReceiveCountWorker>() // (2) val receiveCountWorkRequest = workRequestBuilder.build() // (2) workRequestBuilder = OneTimeWorkRequestBuilder<FinishCountWorker>() // (3) val finishCountWorkRequest = workRequestBuilder.build() // (3) val workManager = WorkManager.getInstance(this@MainActivity) // (4) var workContinuation = workManager.beginWith(createCountWorkRequest) // (5) workContinuation = workContinuation.then(receiveCountWorkRequest) // (6) workContinuation = workContinuation.then(finishCountWorkRequest) // (7) workContinuation.enqueue() // (8)
リスト1、リスト2ともに、(1)〜(3)は、それぞれのワーカーのためのWorkRequestを生成しているコードです。(1)でCreateCountWorkerのcreateCountWorkRequest、(2)でReceiveCountWorkerのreceiveCountWorkRequest、(3)でFinishCountWorkerのfinishCountWorkRequestを生成しています。
このうち、まず、CreateCountWorkerから起動するので、(4)で取得したWorkManagerオブジェクトに対して、createCountWorkRequestを登録します。その際に利用するメソッドは、enqueue()などのキュー登録ではなく、(5)のbeginWith()です。
beginWith()メソッドの戻り値は、WorkContinuationオブジェクトです。このWorkContinuationオブジェクトのthen()メソッドを実行し、引数として、beginWith()で渡したワーカーに続けて実行するワーカーのWorkRequestを渡します。
then()メソッドの戻り値もWorkContinuationオブジェクトなので、(6)や(7)のように続けて何回でもthen()メソッドを実行できます。そして、then()を実行した順序通りに、引数として渡されたWorkRequestのワーカーが実行されるようになっています。リスト1やリスト2では、(6)でreceiveCountWorkRequestを、(7)でfinishCountWorkRequestを渡しています。
結果的に、以下の順序でワーカーが実行されるようになります
CreateCountWorker → ReceiveCountWorker → FinishCountWorker
ただし、そのためには、最終的には、WorkManagerのキューに登録する必要があります。それが、(8)のWorkContinuationオブジェクトのenqueue()メソッドの実行です。
なお、リスト1やリスト2の(5)〜(8)は、その仕組みを紹介するためにそれぞれ別の行として記述しています。これらは、メソッドチェーンを採用して、次の1行記述でも問題なく動作します。公式ドキュメントでは、このコードパターンで紹介しています。
workManager .beginWith(createCountWorkRequest) .then(receiveCountWorkRequest) .then(finishCountWorkRequest) .enqueue();