將 WorkRequest
排入佇列後,WorkManager 可讓您更新該物件。對於經常變更限製或需要即時更新工作站的大型應用程式而言,通常這是不可或缺的步驟。自 WorkManager 2.8.0 版起,updateWork()
API 是這樣做的方法。
updateWork()
方法可讓您即時變更 WorkRequest
的某些部分,不必執行手動取消並排入新的程序。這可大幅簡化開發程序
避免取消工作
一般而言,您應避免取消現有的 WorkRequest 並將新的 WorkRequest 排入佇列。這樣做可能會導致應用程式重複執行特定工作,而您可能需要編寫大量的額外程式碼。
請參考以下範例,瞭解取消 WorkRequest 可能會造成困難的地方:
- 後端要求:如果您在計算要傳送至伺服器的酬載時取消
Worker
,新的Worker
就必須重新開始,並重新運算可能昂貴的酬載。 - 排程:如果您取消
PeriodicWorkRequest
,並希望新的PeriodicWorkRequest
在相同排程中執行,就必須計算時間偏移,確保新的執行時間與先前的工作要求一致。
updateWork()
API 可讓您更新工作要求的限制條件和其他參數,而不會取消並排入新的要求。
取消工作的時機
在某些情況下,您應該直接取消 WorkRequest
,而不是呼叫 updateWork()
。當您要變更已排入佇列的工作的基本性質時,請執行以上操作。
更新工作時間
假設有一個相片應用程式每天備份使用者的相片。該應用程式已將 PeriodicWorkRequest
加入佇列,以便執行此作業。WorkRequest
設有限制,需要裝置充電並連上 Wi-Fi。
不過,使用者只要使用快速充電器,每天僅為裝置充電 20 分鐘。在這種情況下,應用程式可能需要更新 WorkRequest
來放寬充電限制,即使裝置未充飽電,仍可上傳相片。
在這種情況下,您可以使用 updateWork()
方法更新工作要求的限制條件。
如何更新工作
updateWork()
方法提供更新現有 WorkRequest
的簡易方法,不必取消新的帳戶並將其排入佇列。
如要使用更新已排入佇列的工作,請按照下列步驟操作:
- 取得已排入佇列的工作的現有 ID:取得要更新的 WorkRequest 的 ID。您可以使用任何
getWorkInfo
API 擷取這個 ID,也可以手動保留初始 WorkRequest 中的 ID,以便日後透過公開屬性WorkRequest.id
擷取,然後再排入佇列。 - 建立新的 WorkRequest:建立新的
WorkRequest
,並使用WorkRequest.Builder.setID()
將其 ID 設定為與現有WorkRequest
相符。 - 設定限制:使用
WorkRequest.Builder.setConstraints()
傳遞 WorkManager 新的限制。 - 呼叫 updateWork:將新的 WorkRequest 傳遞至
updateWork()
。
更新工作範例
以下是 Kotlin 的程式碼片段範例,示範如何使用 updateWork()
方法變更用於上傳相片的 WorkRequest
電池限制:
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
時,其產生就會加 1。這可讓您確切追蹤目前排入佇列的 WorkRequest
。產生版本可讓您進一步掌控在觀察、追蹤和測試工作要求時。
如要取得 WorkRequest
的產生,請按照下列步驟操作:
- WorkInfo:呼叫
WorkManager.getWorkInfoById()
以擷取對應於WorkRequest
的WorkInfo
執行個體。- 您可以呼叫其中一種傳回
WorkInfo
的方法。詳情請參閱 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
排入佇列。如果有多個待處理 PeriodicWorkRequest
具有相同的不重複 id
,新的工作要求就會取消並刪除。這項政策現已淘汰,改用 ExistingPeriodicWorkPolicy.UPDATE
的工作流程。
舉例來說,將 enqueueUniquePeriodicWork
與 PeriodicWorkRequest
搭配使用時,您可以使用 ExistingPeriodicWorkPolicy.UPDATE
政策初始化新的 PeriodicWorkRequest
。如果如果有待處理 PeriodicWorkRequest
且名稱不重複,WorkManager 會將其更新為新的規格。根據這個工作流程,您並不需要使用 updateWork()
。