Android WorkManager 背景任務處理
在 Android 開發中,處理背景任務有許多選擇(如 Coroutines, Services),但當你需要執行「即使 App 關閉或裝置重啟也要保證執行」且「可延遲執行」的任務時,WorkManager 是唯一的標準解答。
核心概念與優勢
WorkManager 並不是另一種執行緒方案,它是系統層級的任務排程器:
- 持久性 (Persistence):任務資訊存於資料庫,手機重啟後仍會繼續執行。
- 條件約束 (Constraints):可以設定「充電時」、「有網路」或「空間足夠」時才執行。
- 適配性:自動根據 API Level 選擇底層實作(JobScheduler 或 AlarmManager)。
定位與實作 Worker
我們建議使用 CoroutineWorker,它能讓你以非同步且非阻塞的方式撰寫背景邏輯。
定位 Worker
class ImageUploadWorker(
appContext: Context,
params: WorkerParameters
) : CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
// 接收傳入的參數
val imageUri = inputData.getString("IMAGE_URI") ?: return Result.failure()
return try {
// 執行耗時工作 (如上傳)
val outputUrl = uploadImage(imageUri)
// 回傳成功並帶回結果
val outputData = workDataOf("URL" to outputUrl)
Result.success(outputData)
} catch (e: Exception) {
// 判斷是否需要自動重試
if (runAttemptCount < 3) Result.retry() else Result.failure()
}
}
}
提交任務請求 (WorkRequest)
加入條件與重試策略
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED) // 僅限 WiFi
.setRequiresCharging(true) // 必須在充電
.build()
val uploadRequest = OneTimeWorkRequestBuilder<ImageUploadWorker>()
.setConstraints(constraints)
.setInputData(workDataOf("IMAGE_URI" to "content://..."))
.setBackoffCriteria(
BackoffPolicy.EXPONENTIAL, // 指數退避 (越來越慢重試)
OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS
)
.addTag("upload_tag") // 用於篩選或取消任務
.build()
WorkManager.getInstance(context).enqueue(uploadRequest)
任務鏈與唯一任務
任務鏈 (Chaining)
你可以將多個任務串接,系統會保證順序執行,並將前一個任務的輸出傳遞給下一個。
WorkManager.getInstance(context)
.beginWith(filterWork) // 步驟 1: 濾鏡處理
.then(compressWork) // 步驟 2: 圖片壓縮
.then(uploadWork) // 步驟 3: 上傳伺服器
.enqueue()
唯一任務 (Unique Work)
避免重複提交相同的長效任務(例如:重複點擊「立即備份」按鈕)。
WorkManager.getInstance(context).enqueueUniqueWork(
"daily_sync",
ExistingWorkPolicy.KEEP, // 如果已在隊列中,則保留舊的,忽略新的
syncRequest
)
整合 Hilt 依賴注入
在大型專案中,Worker 通常需要呼叫 API 或資料庫,這時需要整合 Hilt。
- 使用
@HiltWorker註解。 - 在建構子加入
@AssistedInject。
@HiltWorker
class SyncWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted params: WorkerParameters,
private val repository: DataRepository // 注入你的單例
) : CoroutineWorker(context, params) { ... }
背景處理方案選擇指南
下表能幫助你根據任務特性選擇正確的技術:
| 任務特性 | 建議技術 | 範例 |
|---|---|---|
| 立即執行,使用者在看 | Coroutines / Flow | 獲取當前頁面列表 |
| 可延遲,與 UI 無關 | WorkManager | 雲端備份、資料同步 |
| 長時間進行,需通知用戶 | Foreground Service | 音樂播放、導航 |
| 精確時間點 | AlarmManager | 鬧鐘設定 |
透過 WorkManager,你能確保 App 在節省系統資源(如電量)的同時,仍具備高度的任務可靠性。