ワーカーの状態把握とキャンセル処理
最後に、ワーカーをキャンセルする方法を紹介します。
ワーカーの状態把握はLiveDataを利用
前回のワーカーの状態の図1にもあるように、ワーカーがENQUEUED状態、あるいは、RUNNING状態の場合は、キャンセル処理が可能です。そのためには、まず、ワーカーの状態を把握する必要があります。例えば図1のように、ワーカーの実行ボタンとキャンセルボタンを実装するとして、ユーザビリティを考えると、ワーカーの実行前はキャンセルができないようにしておく必要があります。同様に、ワーカーが実行中(RUNNING状態)の場合は図2のように、待機状態(ENQUEUED状態)の場合は図3のように、キャンセルボタンがタップできるようにする必要があります。
このようにワーカーの状態に応じてボタンなどの表示を変更する場合、第4回で紹介したLiveDataとオブザーバを利用するのが便利です。なぜならWorkManagerには、ワーカーの状態が格納されたLiveDataを取得するメソッドがいくつか用意されているからです。このメソッドは、引数に応じて表2のものが存在します。
メソッドと引数 | 戻り値 |
---|---|
getWorkInfoByIdLiveData(UUID id) | LiveData<WorkInfo> |
getWorkInfosByTagLiveData(String tag) | LiveData<List<WorkInfo>> |
getWorkInfosForUniqueWorkLiveData(String uniqueWorkName) | LiveData<List<WorkInfo>> |
getWorkInfoByIdLiveData()以外は、引数がワーカーを検索するためのタグ文字列やenqueueUniqueWork()の第1引数で渡したユニークワーカーの識別文字列となっているため、複数のワーカーが存在することになります。そのため、戻り値は、ListのLiveDataとなっています。
一方、getWorkInfoByIdLiveData()はワーカー各々を確実に区別するためのIDを表すUUIDオブジェクトを指定するため、単一のワーカーの状態情報を取得できます。そのため、可能ならば、UUIDを利用します。
このUUIDは、WorkRequestのgetId()メソッド(Kotlinの場合はidプロパティ)を利用して取得できます。例えば、Javaならばリスト7、Kotlinならばリスト8のコードでワーカーの状態のLiveDataを取得できます。
UUID uuId = workRequest.getId(); LiveData<WorkInfo> workInfoLiveData = workManager.getWorkInfoByIdLiveData(uuId);
val workInfoLiveData = workManager.getWorkInfoByIdLiveData(workRequest.id)
ワーカーの状態はWorkInfoから取得
LiveDataのジェネリクスとして指定しているWorkInfoは、まさにワーカーの状態を表すクラスであり、このWorkInfo内の値を利用して、状態に応じた表示処理の分岐などを行なっていきます。そのため、このLiveDataに登録するオブザーバクラスは、Javaならばリスト9、Kotlinならばリスト10のようなコードになります。
private class WorkInfoLiveDataObserver implements Observer<WorkInfo> { @Override public void onChanged(WorkInfo workInfo) { if(workInfo.getState() == WorkInfo.State.ENQUEUED) { : } else if(workInfo.getState() == WorkInfo.State.RUNNING) { : } else if(workInfo.getState() == WorkInfo.State.SUCCEEDED) { : } else if(workInfo.getState() == WorkInfo.State.CANCELLED) { : } } }
private inner class WorkInfoLiveDataObserver : Observer<WorkInfo> { override fun onChanged(workInfo: WorkInfo) { if(workInfo.state == WorkInfo.State.ENQUEUED) { : } else if(workInfo.state == WorkInfo.State.RUNNING) { : } else if(workInfo.state == WorkInfo.State.SUCCEEDED) { : } else if(workInfo.state == WorkInfo.State.CANCELLED) { : } } }
WorkInfoクラスには、該当するワーカーの現在の状態を取得するgetState()メソッド(Kotlinではstateプロパティ)があり、その値はWorkInfoのメンバenumであるStateとなっています。
よって、リスト9やリスト10のような分岐を記述し、その中で状態に応じた処理を記述します。図1〜図3のボタンの表示切り替えは、このようにしています。
ワーカーをキャンセルするメソッド
ワーカーをキャンセルする場合も、WorkManagerには引数違いでいくつかのメソッドが用意されており、まとめると、表3のとおりです。
メソッド名 | 内容 |
---|---|
cancelAllWork() | 終了していない全てのワーカーをキャンセル |
cancelAllWorkByTag(String tag) | 引数のタグに該当する全てのワーカーをキャンセル |
cancelUniqueWork(String uniqueWorkName) | ユニークワーカーを識別文字列で指定してキャンセル |
cancelWorkById(UUID id) | UUIDを指定して該当ワーカーをキャンセル |
例えばリスト6のように、UniqueKeepRetry識別文字列で起動したユニークワーカーをキャンセルする場合は、JavaでもKotlinでもリスト11のコードになります。このコードだけで、ワーカーがキャンセルされます。
workManager.cancelUniqueWork("UniqueKeepRetry")
もしワーカーがキャンセルされた時の処理をワーカーに定義したい場合は、ワーカークラスにonStopped()メソッドをオーバーライドして処理を記述します。
まとめ
Android Jetpackについて紹介していく本連載の第10回は、いかがでしたでしょうか。
今回は、WorkManagerの2回目として、ワーカーにデータを渡す方法や再実行の制御、複数起動の制御、さらには、ワーカーの状態を把握するとともにキャンセルを行う方法を紹介しました。次回は、WorkManagerを紹介する最後として、繰り返しのワーカーや、ワーカーのチェイン、優先実行のワーカーを紹介します。