再実行の制御
次に紹介するのは、再実行の制御です。
制御を指定するsetBackoffCriteria()メソッド
前回のdoWork()の戻り値で紹介したように、doWork()メソッドの戻り値をResult.retry()とすると、そのワーカーは再実行されます。より厳密にいうと、そのワーカーは、ENQUEUED状態に戻され、適切なタイミングで再びRUNNING状態に移行します。この「適切なタイミング」というのを、実は制御できるようになっています。
その際利用するのが、WorkRequestのビルダーのメソッドsetBackoffCriteria()です。コード例としては、JavaでもKotlinでも変わらず、リスト5のようになります。
workRequestBuilder.setBackoffCriteria(BackoffPolicy.LINEAR, 15, TimeUnit.SECONDS)
再実行の間隔を指定する引数
setBackoffCriteria()メソッドは引数を3個必要とします。順番は前後しますが、第2引数と第3引数を先に説明します。この2個の引数は、ワンセットで再実行までの間隔を指定します。これを、公式ドキュメントでは、Backoff Delayと表現しています。第2引数が数値を表し、第3引数が第2引数の単位を表します。
この仕組みは、前回紹介したWorkRequestのビルダーのsetInitialDelay()メソッドの引数と同じ仕組みとなっており、リスト5の例では、再実行までの間隔が15秒となっています。
ただし、この間隔は、最小値と最大値が決まっており、その間で指定する必要があります。最小値は、WorkRequest.MIN_BACKOFF_MILLIS定数で表されるミリセカンド値であり、現在10000ミリセカンド(=10秒)となっています。最大値は、同じくWorkRequest.MAX_BACKOFF_MILLIS定数で表されるミリセカンド値であり、現在18000000ミリセカンド(=30分)となっています。
なお、このBackoff Delayのデフォルト値は、定数WorkRequest.DEFAULT_BACKOFF_DELAY_MILLISで表されるミリセカンド値であり、現在30000ミリセカンド(=30秒)となっています。よって、setBackoffCriteria()メソッドを実行しない場合、ENQUEUED状態に戻されたワーカーは30秒後に再実行されることになります。
再実行間隔の増加方法を指定する引数
setBackoffCriteria()メソッドの第1引数は、BackoffPolicyの定数(正確にはenumの列挙子)を指定し、以下の2個のどちらかを選択します。これは、再実行時すなわち、2回目のワーカーの実行後もENQUEUED状態に戻され、さらに再実行が必要な場合は、再実行までの間隔をどのように増加させるかを指定する定数です。デフォルトは、EXPONENTIALとなっています。
EXPONENTIAL
再実行までの間隔が、倍々の値で増加します。例えば、リスト5のように、Backoff Delayが15秒ならば、2回目は初回終了後の15秒後、3回目は2回目終了後の30秒後、4回目は3回目終了後の60秒後、5回目は4回目終了後の120秒後、…、のような増加となります。
LINEAR
再実行までの間隔が、単純にBackoff Delayの値が足し合わされた値で増加します。例えば、同様に、Backoff Delayが15秒ならば、2回目は初回終了後の15秒後、3回目は2回目終了後の30秒後、4回目は45秒後、5回目は60秒後、…、のような増加となります。
ワーカーの複数起動の制御
次に、ワーカーの複数起動に関する制御を紹介します。
ワーカーを単一起動するenqueueUniqueWork()メソッド
例えば、前回紹介したCountUpWorkerワーカーを起動するコードをボタンをタップした際の処理として記述していたとします。その状態で、ボタンを複数回タップすると、CountUpWorkerワーカーはタップした回数分だけキュー登録されます。
このような状態を避けるための仕組みがWorkManagerには用意されており、起動するワーカーをユニーク(単一)の状態に保つことができます。その場合は、WorkManagerからワーカーをキュー登録する際のメソッドとしてenqueue()の代わりに、enqueueUniqueWork()を使います。このメソッドの使い方は、JavaでもKotlinでも同じであり、例えば、リスト6のようなコードです。
workManager.enqueueUniqueWork("UniqueKeepRetry", ExistingWorkPolicy.KEEP, workRequest)
enqueue()メソッドの場合は引数は1個であり、WorkRequestオブジェクトを渡します。一方、enqueueUniqueWork()メソッドの引数は3個必要であり、WorkRequestオブジェクトは第3引数として渡します。
第1引数は、ここでキュー登録するワーカー(より正確にはそのワーカーの制御に関するWorkRequest)を識別するための文字列です。
起動が重なった際の制御を指定する第2引数
enqueueUniqueWork()メソッドの第2引数は、キュー登録が重なった際にどのような対応をするのかを指定する引数であり、ExistingWorkPolicyの定数(正確にはenumの列挙子)で指定します。どのような列挙子があるのかは、表1にまとめておきます。
列挙子 | 内容 |
---|---|
KEEP | 現在のワーカーをそのまま維持し、後からキュー登録したものは破棄します。 |
REPLACE | 現在のワーカーをキャンセルし、後からキュー登録したものに置き換えます。 |
APPEND | 現在のワーカーをそのまま維持し、後からキュー登録したワーカーを現在のワーカーが終了した後に起動します。 |
APPEND_OR_REPLACE | APPENDとほぼ同じですが、FAILED、あるいは、CANCELLED時の挙動が違います。 |
表1のAPPEND_OR_REPLACEに関して、少し補足します。KEEP、REPLACE、APPENDに関しては、先に起動したワーカーがFAILED、あるいは、CANCELLED状態の場合、後からキュー登録したワーカーも同様のFAILED、あるいは、CANCELLED状態に自動的に移行します。もし、先に起動したワーカーがFAILED、あるいは、CANCELLED状態だとしても、先に起動したワーカーの終了後に後からキュー登録したワーカーを起動したい場合は、APPEND_OR_REPLACEを指定します。