kotlin 156 lines · 2 tabs

WorkManager for background tasks

Alex Chen Jan 2026
2 tabs
package com.example.myapp.workers

import android.content.Context
import androidx.hilt.work.HiltWorker
import androidx.work.*
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import java.util.concurrent.TimeUnit

@HiltWorker
class SyncWorker @AssistedInject constructor(
    @Assisted context: Context,
    @Assisted params: WorkerParameters,
    private val repository: PostRepository
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        return try {
            // Get input data
            val forceRefresh = inputData.getBoolean(KEY_FORCE_REFRESH, false)

            setProgress(workDataOf(PROGRESS to 0))

            repository.syncPosts(forceRefresh)

            setProgress(workDataOf(PROGRESS to 100))

            // Return success with output data
            Result.success(
                workDataOf(
                    KEY_SYNC_TIME to System.currentTimeMillis()
                )
            )
        } catch (e: Exception) {
            if (runAttemptCount < 3) {
                Result.retry()
            } else {
                Result.failure(
                    workDataOf(KEY_ERROR to e.message)
                )
            }
        }
    }

    companion object {
        const val KEY_FORCE_REFRESH = "force_refresh"
        const val KEY_SYNC_TIME = "sync_time"
        const val KEY_ERROR = "error"
        const val PROGRESS = "progress"

        fun schedulePeriodicSync(context: Context) {
            val constraints = Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .setRequiresBatteryNotLow(true)
                .build()

            val syncRequest = PeriodicWorkRequestBuilder<SyncWorker>(
                15, TimeUnit.MINUTES
            )
                .setConstraints(constraints)
                .setBackoffCriteria(
                    BackoffPolicy.EXPONENTIAL,
                    10, TimeUnit.SECONDS
                )
                .build()

            WorkManager.getInstance(context)
                .enqueueUniquePeriodicWork(
                    "sync_posts",
                    ExistingPeriodicWorkPolicy.KEEP,
                    syncRequest
                )
        }

        fun scheduleOneTimeSync(
            context: Context,
            forceRefresh: Boolean = false
        ) {
            val inputData = workDataOf(KEY_FORCE_REFRESH to forceRefresh)

            val syncRequest = OneTimeWorkRequestBuilder<SyncWorker>()
                .setInputData(inputData)
                .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
                .build()

            WorkManager.getInstance(context)
                .enqueueUniqueWork(
                    "sync_posts_once",
                    ExistingWorkPolicy.REPLACE,
                    syncRequest
                )
        }
    }
}
2 files · kotlin Explain with highlit

WorkManager schedules deferrable, guaranteed background work. I create Worker or CoroutineWorker subclasses with doWork() method. Constraints specify when work runs—network type, charging status, battery level. One-time requests use OneTimeWorkRequest, periodic work uses PeriodicWorkRequest with minimum 15-minute intervals. Chaining enables dependent tasks with then() and combine(). Work survives app restarts and device reboots. Data objects pass parameters in/out. I observe work status with WorkInfo LiveData. Unique work ensures single instances with conflict policies. WorkManager handles scheduling across API levels, using JobScheduler, AlarmManager, or BroadcastReceiver based on device capabilities.


Related snips

Share this code

Here's the card — post it anywhere.

WorkManager for background tasks — share card
Link copied