WorkManager
1. Giới thiệu
Phần tiêu đề “1. Giới thiệu”WorkManager xử lý background tasks cần đảm bảo thực thi, ngay cả khi app bị tắt.
2. Khi nào dùng WorkManager?
Phần tiêu đề “2. Khi nào dùng WorkManager?”| Use Case | Solution |
|---|---|
| Sync data định kỳ | WorkManager |
| Upload logs | WorkManager |
| Download files | WorkManager |
| Immediate user task | Coroutines |
| Foreground task | Foreground Service |
3. Setup
Phần tiêu đề “3. Setup”dependencies { implementation("androidx.work:work-runtime-ktx:2.9.0")}4. Tạo Worker
Phần tiêu đề “4. Tạo Worker”class UploadWorker( context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) {
override suspend fun doWork(): Result { return try { val imageUri = inputData.getString("image_uri") ?: return Result.failure()
// Upload logic uploadImage(imageUri)
// Return success with output val outputData = workDataOf("upload_url" to "https://...") Result.success(outputData) } catch (e: Exception) { if (runAttemptCount < 3) { Result.retry() } else { Result.failure() } } }}5. Schedule Work
Phần tiêu đề “5. Schedule Work”One-time Work
Phần tiêu đề “One-time Work”val uploadRequest = OneTimeWorkRequestBuilder<UploadWorker>() .setInputData(workDataOf("image_uri" to uri.toString())) .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresBatteryNotLow(true) .build() ) .setBackoffCriteria( BackoffPolicy.EXPONENTIAL, 30, TimeUnit.SECONDS ) .addTag("upload") .build()
WorkManager.getInstance(context).enqueue(uploadRequest)Periodic Work
Phần tiêu đề “Periodic Work”val syncRequest = PeriodicWorkRequestBuilder<SyncWorker>( 15, TimeUnit.MINUTES // Minimum 15 minutes) .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build() ) .build()
WorkManager.getInstance(context) .enqueueUniquePeriodicWork( "sync_work", ExistingPeriodicWorkPolicy.KEEP, syncRequest )6. Constraints
Phần tiêu đề “6. Constraints”val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) // Cần network .setRequiredNetworkType(NetworkType.UNMETERED) // Cần WiFi .setRequiresBatteryNotLow(true) // Battery > 20% .setRequiresCharging(true) // Đang sạc .setRequiresDeviceIdle(true) // Device idle .setRequiresStorageNotLow(true) // Storage ok .build()7. Work Chaining
Phần tiêu đề “7. Work Chaining”WorkManager.getInstance(context) .beginWith(downloadRequest) .then(processRequest) .then(uploadRequest) .enqueue()
// Parallel then sequentialWorkManager.getInstance(context) .beginWith(listOf(download1, download2, download3)) .then(mergeRequest) .then(uploadRequest) .enqueue()8. Observe Work Status
Phần tiêu đề “8. Observe Work Status”WorkManager.getInstance(context) .getWorkInfoByIdLiveData(uploadRequest.id) .observe(lifecycleOwner) { workInfo -> when (workInfo?.state) { WorkInfo.State.ENQUEUED -> showPending() WorkInfo.State.RUNNING -> showProgress() WorkInfo.State.SUCCEEDED -> { val url = workInfo.outputData.getString("upload_url") showSuccess(url) } WorkInfo.State.FAILED -> showError() WorkInfo.State.CANCELLED -> showCancelled() else -> {} } }
// With FlowWorkManager.getInstance(context) .getWorkInfoByIdFlow(uploadRequest.id) .collect { workInfo -> // Handle state }9. Cancel Work
Phần tiêu đề “9. Cancel Work”// By IDWorkManager.getInstance(context).cancelWorkById(uploadRequest.id)
// By tagWorkManager.getInstance(context).cancelAllWorkByTag("upload")
// By unique nameWorkManager.getInstance(context).cancelUniqueWork("sync_work")
// AllWorkManager.getInstance(context).cancelAllWork()10. Progress Updates
Phần tiêu đề “10. Progress Updates”class DownloadWorker(...) : CoroutineWorker(...) {
override suspend fun doWork(): Result { val files = inputData.getStringArray("files") ?: return Result.failure()
files.forEachIndexed { index, file -> downloadFile(file)
// Update progress setProgress(workDataOf("progress" to (index + 1) * 100 / files.size)) }
return Result.success() }}
// Observe progressworkManager.getWorkInfoByIdFlow(request.id).collect { info -> val progress = info?.progress?.getInt("progress", 0) ?: 0 updateProgressBar(progress)}11. Expedited Work (Android 12+)
Phần tiêu đề “11. Expedited Work (Android 12+)”val urgentRequest = OneTimeWorkRequestBuilder<UrgentWorker>() .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .build()12. Hilt Integration
Phần tiêu đề “12. Hilt Integration”@HiltWorkerclass SyncWorker @AssistedInject constructor( @Assisted context: Context, @Assisted workerParams: WorkerParameters, private val repository: DataRepository) : CoroutineWorker(context, workerParams) {
override suspend fun doWork(): Result { repository.sync() return Result.success() }}📝 Tóm tắt
Phần tiêu đề “📝 Tóm tắt”| Feature | Description |
|---|---|
| OneTimeWorkRequest | Chạy một lần |
| PeriodicWorkRequest | Chạy định kỳ (min 15 phút) |
| Constraints | Điều kiện để chạy |
| Chaining | Nối nhiều work |
| Result.retry() | Thử lại nếu fail |
| setExpedited() | Ưu tiên cao |