WorkManager では、WorkRequest
をキューに追加した後で更新できます。これは、制約を頻繁に変更する場合や、ワーカーをその場で更新する必要がある大規模なアプリで必要になることがよくあります。WorkManager バージョン 2.8.0 以降では、updateWork()
API がこれを行う手段になっています。
updateWork()
メソッドを使用すると、新しい要素を手動でキャンセルしてキューに登録するプロセスを必要とせずに、WorkRequest
の特定の要素をその場で変更できます。これにより、開発プロセスが大幅に簡素化されます。
処理のキャンセルを避ける
通常は、既存の WorkRequest のキャンセルや新しい WorkRequest のキュー登録は避けてください。このように設定すると、アプリが特定のタスクを繰り返して、大量の追加コードを記述する必要が生じる場合があります。
WorkRequest のキャンセルがうまくいかない場合の例を以下に示します。
- バックエンド リクエスト: サーバーに送信するペイロードの計算中に
Worker
をキャンセルすると、新しいWorker
を最初からやり直し、高価な可能性があるペイロードを再計算する必要があります。 - スケジュール:
PeriodicWorkRequest
をキャンセルし、新しいPeriodicWorkRequest
を同じスケジュールで実行する場合は、新しい実行時間が前の処理リクエストと一致するように時間オフセットを計算する必要があります。
updateWork()
API を使用すると、新しいリクエストをキャンセルしてキューに入れることなく、処理リクエストの制約やその他のパラメータを更新できます。
処理をキャンセルするタイミング
updateWork()
を呼び出すのではなく、WorkRequest
を直接キャンセルする必要がある場合があります。これは、キューに投入した処理の基本的な性質を変更したい場合に行います。
提出物を更新するタイミング
ユーザーの写真を毎日バックアップする写真アプリを例に考えます。そのために PeriodicWorkRequest
がキューに追加されています。WorkRequest
には、デバイスを充電して Wi-Fi に接続する必要があるという制約があります。
しかし、ユーザーが急速充電器を使ってデバイスを充電するのは 1 日に 20 分間だけです。この場合、アプリは WorkRequest
を更新して充電の制約を緩和し、デバイスが完全に充電されていない場合でも写真をアップロードできるようにすることをおすすめします。
この場合、updateWork()
メソッドを使用して処理リクエストの制約を更新できます。
提出物を更新する方法
updateWork()
メソッドを使用すると、既存の WorkRequest
を簡単に更新できます。新しい WorkRequest
をキャンセルしてキューに登録する必要はありません。
キューに追加された処理を更新する手順は次のとおりです。
- キューに追加された処理の既存の ID を取得する: 更新する WorkRequest の ID を取得します。この ID は、いずれかの
getWorkInfo
API を使用して取得できます。また、最初の WorkRequest から ID を手動で保持して、後でパブリック プロパティWorkRequest.id
を使用して取得できるようにキューに登録することもできます。 - 新しい WorkRequest を作成する: 新しい
WorkRequest
を作成し、WorkRequest.Builder.setID()
を使用して既存のWorkRequest
の ID と一致する ID を設定します。 - 制約を設定する:
WorkRequest.Builder.setConstraints()
を使用して WorkManager の新しい制約を渡します。 - updateWork を呼び出す: 新しい WorkRequest を
updateWork()
に渡します。
更新(仕事用)の例
以下に、写真のアップロードに使用する WorkRequest
のバッテリー制約を、updateWork()
メソッドを使用して変更するコード スニペットを Kotlin で示します。
suspend fun updatePhotoUploadWork() {
// Get instance of WorkManager.
val workManager = WorkManager.getInstance(context)
// Retrieve the work request ID. In this example, the work being updated is unique
// work so we can retrieve the ID using the unique work name.
val photoUploadWorkInfoList = workManager.getWorkInfosForUniqueWork(
PHOTO_UPLOAD_WORK_NAME
).await()
val existingWorkRequestId = photoUploadWorkInfoList.firstOrNull()?.id ?: return
// Update the constraints of the WorkRequest to not require a charging device.
val newConstraints = Constraints.Builder()
// Add other constraints as required here.
.setRequiresCharging(false)
.build()
// Create new WorkRequest from existing Worker, new constraints, and the id of the old WorkRequest.
val updatedWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(newConstraints)
.setId(existingWorkRequestId)
.build()
// Pass the new WorkRequest to updateWork().
workManager.updateWork(updatedWorkRequest)
}
結果を処理する
updateWork()
は ListenableFuture<UpdateResult>
を返します。指定された UpdateResult
には、WorkManager が変更を適用できたかどうかを示すいくつかの値のいずれかを指定できます。また、変更を適用できた日時も示されます。
詳細については、updateWork()
と UpdateResult
のリファレンスをご覧ください。
世代とともに仕事を追跡する
WorkRequest
を更新するたびに、generation が 1 ずつ増えます。これにより、現在キューに追加されている WorkRequest
を正確に追跡できます。世代を使用すると、処理リクエストのモニタリング、トレース、テストをより細かく制御できます。
WorkRequest
の生成を取得する手順は次のとおりです。
- WorkInfo:
WorkManager.getWorkInfoById()
を呼び出して、WorkRequest
に対応するWorkInfo
のインスタンスを取得します。WorkInfo
を返すいくつかのメソッドの 1 つを呼び出すことができます。詳細については、WorkManager リファレンスをご覧ください。
- getGeneration:
WorkInfo
のインスタンスでgetGeneration()
を呼び出します。返されるInt
は、WorkRequest
の世代に対応します。- 世代フィールドやプロパティはなく、
WorkInfo.getGeneration()
メソッドのみがあることに注意してください。
- 世代フィールドやプロパティはなく、
トラック生成の例
WorkRequest
の世代を取得するための上記のワークフローの実装例を次に示します。
// Get instance of WorkManager.
val workManager = WorkManager.getInstance(context)
// Retrieve WorkInfo instance.
val workInfo = workManager.getWorkInfoById(oldWorkRequestId)
// Call getGeneration to retrieve the generation.
val generation = workInfo.getGeneration()
課題の更新に関するポリシー
以前は、定期的な処理を更新するための推奨ソリューションは、ポリシー ExistingPeriodicWorkPolicy.REPLACE
を使用して PeriodicWorkRequest
をキューに追加することでした。同じ一意の id
を持つ保留中の PeriodicWorkRequest
がある場合、新しい処理リクエストはキャンセルされて削除されます。このポリシーは非推奨となり、ExistingPeriodicWorkPolicy.UPDATE
を使用したワークフローに置き換えられました。
たとえば、PeriodicWorkRequest
で enqueueUniquePeriodicWork
を使用する場合、ExistingPeriodicWorkPolicy.UPDATE
ポリシーで新しい PeriodicWorkRequest
を初期化できます。同じ一意名を持つ保留中の PeriodicWorkRequest
がある場合、WorkManager はそれを新しい仕様に更新します。このワークフローに従うと、updateWork()
を使用する必要はありません。