Work requests, constraints, data, progress, and cancellation
WorkManager stores a request, evaluates constraints, runs a Worker, and records its state. It guarantees eligible work is scheduled, not that every server operation succeeds.
One-time and periodic requests
val oneTime = OneTimeWorkRequestBuilder<ThumbnailWorker>()
.addTag("thumbnail:$assetId")
.setInputData(workDataOf("assetId" to assetId))
.build()
val periodic = PeriodicWorkRequestBuilder<FeedSyncWorker>(6, TimeUnit.HOURS)
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build()
)
.build()
Periodic work is inexact and has a platform-enforced minimum interval. Runs can be delayed by constraints, Doze, quotas, or system load.
Data is a small control envelope
class ThumbnailWorker(
appContext: Context,
params: WorkerParameters,
) : CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
val assetId = inputData.getString("assetId")
?: return Result.failure(workDataOf("reason" to "missing_id"))
// Load the real record/file using assetId.
return Result.success(workDataOf("assetId" to assetId))
}
}
Data supports a limited set of value types and has a size limit. Store business payloads in Room/files; pass keys through WorkManager.
Progress is observable, not durable business truth
setProgress(workDataOf("uploadedBytes" to sent, "totalBytes" to total))
The UI can observe WorkInfo, but a progress percentage can reset when a worker retries. Store completed upload parts/checkpoints durably when resume correctness matters.
Cancellation is cooperative
workManager.cancelUniqueWork("receipt-upload-$receiptId")
Cancellation changes WorkManager state and stops the worker. Suspending APIs should cooperate with coroutine cancellation. A remote HTTP request already accepted by the server may still complete; cancellation is not a distributed rollback.
Practical state model
ENQUEUED -> RUNNING -> SUCCEEDED
-> FAILED
-> ENQUEUED (retry/backoff)
ENQUEUED/RUNNING -> CANCELLED
BLOCKED -> ENQUEUED when prerequisites finish
Common mistakes
- ❌ Pass a 5 MB image in
Data. - ✅ Persist the URI/file and pass its stable ID.
- ❌ Display “upload cancelled” as proof the server removed it.
- ✅ Model remote cancellation/compensation separately.
- ❌ Use periodic work as a clock.
- ✅ Design periodic work to tolerate delayed and skipped opportunities.
Sources
Exercise
Build an upload screen that survives rotation, shows WorkInfo state, and loads the final server result from Room rather than treating output Data as the source of truth.