Background Work Boundaries
Use the smallest background mechanism that matches the user promise.
| Work | Use | Do Not Use |
|---|---|---|
| In-screen async work | Coroutine in viewModelScope or repository scope | WorkManager |
| Reliable deferrable work | WorkManager | Raw threads or one-off coroutines |
| Exact alarm | AlarmManager, only when exact timing is truly required | WorkManager for clock-precise promises |
| User-visible long-running work | Foreground service or long-running Worker with notification | Silent background loops |
| Incoming platform event | Broadcast receiver, then hand off quickly | Heavy parsing directly in receiver |
WorkManager Fits
Use WorkManager when the work should survive app exit or device reboot:
- export backup after user request
- periodic local cleanup
- deferred sync when network is available
- retryable upload of user-approved diagnostics
- post-import processing that can resume later
WorkManager gives you constraints, unique work, chaining, retries/backoff, and persistent scheduling.
WorkManager Does Not Fit
Do not use WorkManager for:
- filtering a list while the screen is visible
- loading initial UI state from a repository
- parsing one SMS synchronously during onboarding
- exact alarm-clock behavior
- continuous background tracking with no user-visible reason
Unique Work Pattern
Use unique names for recurring or replaceable jobs:
val request = OneTimeWorkRequestBuilder<ExportBackupWorker>()
.setConstraints(
Constraints.Builder()
.setRequiresBatteryNotLow(true)
.build(),
)
.build()
WorkManager.getInstance(context).enqueueUniqueWork(
"export-backup",
ExistingWorkPolicy.REPLACE,
request,
)
Worker Boundary
A worker should read durable state, perform one job, and return a clear result.
class ExportBackupWorker(
context: Context,
params: WorkerParameters,
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
// Read from repository or database and write the export.
Result.success()
} catch (retryable: IOException) {
Result.retry()
} catch (fatal: IllegalArgumentException) {
Result.failure()
}
}
}
Device Reality
WorkManager is Doze-aware and persistent, not instant. OEM battery managers can delay work more aggressively than a Pixel emulator. Test important jobs on the device class users actually own.