Android WorkManager 2026: Panduan Lengkap Background Tasks, Constraints, dan Pertanyaan Interview
Pelajari Android WorkManager untuk menjalankan background tasks dengan constraints, chaining, dan CoroutineWorker. Termasuk pertanyaan interview untuk persiapan wawancara kerja Android developer.

Android WorkManager menangani pekerjaan background yang dapat ditunda namun dijamin akan dieksekusi, bahkan setelah aplikasi di-restart atau perangkat di-reboot. Sebagai bagian dari Android Jetpack, WorkManager 2.11.2 (stabil, Maret 2026) menyediakan API terpadu yang bekerja pada API 23+ dengan memilih implementasi terbaik (JobScheduler, AlarmManager, atau Firebase JobDispatcher) berdasarkan level API perangkat.
Gunakan WorkManager untuk tugas yang memerlukan jaminan eksekusi: mengunggah log, menyinkronkan data, memproses gambar. Untuk pekerjaan yang harus segera dilakukan dan tidak perlu bertahan saat proses mati, gunakan Kotlin Coroutines.
Menyiapkan WorkManager 2.11 dalam Proyek Kotlin
Sebelum menulis worker apapun, dependency harus dideklarasikan. WorkManager 2.11+ membutuhkan minSdk 23 dan compileSdk 33.
dependencies {
val workVersion = "2.11.2"
implementation("androidx.work:work-runtime-ktx:$workVersion")
// Optional: for testing
androidTestImplementation("androidx.work:work-testing:$workVersion")
}Artifact work-runtime-ktx menyertakan ekstensi Kotlin dan dukungan Coroutine melalui CoroutineWorker. Tidak diperlukan konfigurasi tambahan untuk penggunaan dasar: WorkManager melakukan inisialisasi sendiri melalui ContentProvider.
Membuat Worker Sederhana dengan doWork()
Kelas Worker meng-override doWork() dan mengembalikan Result. Sistem menjalankan method ini pada background thread.
class SyncWorker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
override fun doWork(): Result {
// Read input data
val userId = inputData.getString("user_id") ?: return Result.failure()
return try {
// Perform sync operation
val syncService = SyncService.getInstance(applicationContext)
syncService.syncUserData(userId)
Result.success()
} catch (e: IOException) {
// Retry on network errors
Result.retry()
} catch (e: Exception) {
// Permanent failure
Result.failure()
}
}
}Terdapat tiga hasil yang mungkin: Result.success() menandakan selesai, Result.failure() menghentikan percobaan ulang, dan Result.retry() menjadwalkan ulang sesuai kebijakan backoff.
Menggunakan CoroutineWorker untuk Suspend Functions
Ketika pekerjaan melibatkan suspend functions (panggilan Retrofit, query Room), CoroutineWorker menghilangkan callback yang bersarang.
class UploadWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val imageUri = inputData.getString("image_uri")
?: return Result.failure()
// Progress reporting (visible in WorkInfo observers)
setProgress(workDataOf("status" to "compressing"))
val compressed = ImageCompressor.compress(imageUri)
setProgress(workDataOf("status" to "uploading"))
return try {
val response = ApiClient.imageService.upload(compressed)
val outputData = workDataOf("url" to response.imageUrl)
Result.success(outputData)
} catch (e: HttpException) {
if (e.code() in 500..599) Result.retry()
else Result.failure()
}
}
}CoroutineWorker.doWork() berjalan pada Dispatchers.Default. Untuk mengganti dispatcher, gunakan withContext() di dalam fungsi.
Mendefinisikan Constraints untuk Eksekusi Bersyarat
Constraints mencegah pekerjaan berjalan sampai kondisi terpenuhi. Hal ini menghemat baterai dan menghindari percobaan yang gagal.
fun scheduleUpload(context: Context, imageUri: String) {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED) // WiFi only
.setRequiresBatteryNotLow(true)
.setRequiresStorageNotLow(true)
.build()
val uploadRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setConstraints(constraints)
.setInputData(workDataOf("image_uri" to imageUri))
.setBackoffCriteria(
BackoffPolicy.EXPONENTIAL,
Duration.ofMinutes(1)
)
.addTag("upload")
.build()
WorkManager.getInstance(context)
.enqueueUniqueWork(
"upload_$imageUri",
ExistingWorkPolicy.KEEP,
uploadRequest
)
}Constraints yang tersedia meliputi jenis jaringan (CONNECTED, UNMETERED, METERED, NOT_ROAMING), level baterai, status pengisian daya, ruang penyimpanan, dan status idle perangkat. WorkManager 2.10+ juga menerima NetworkRequest mentah untuk kontrol jaringan yang lebih detail.
Pertanyaan interview yang umum adalah kapan menggunakan KEEP vs REPLACE di enqueueUniqueWork. KEEP mengabaikan permintaan baru jika pekerjaan dengan nama yang sama sudah ada, REPLACE membatalkan pekerjaan yang ada dan memulai dari awal. Gunakan KEEP untuk upload dimana duplikasi membuang bandwidth, REPLACE untuk sinkronisasi dimana hanya data terbaru yang penting.
Merangkai Work Requests dengan then() dan combine()
Alur kerja yang kompleks memerlukan eksekusi sekuensial dan paralel. WorkManager merangkai work requests menggunakan beginWith() dan then().
fun processAndUploadImages(context: Context, imageUris: List<String>) {
val workManager = WorkManager.getInstance(context)
// Parallel compression workers
val compressRequests = imageUris.map { uri ->
OneTimeWorkRequestBuilder<CompressWorker>()
.setInputData(workDataOf("uri" to uri))
.build()
}
// Single upload worker runs after all compressions complete
val uploadRequest = OneTimeWorkRequestBuilder<BatchUploadWorker>()
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
)
.build()
// Cleanup runs after upload, regardless of success
val cleanupRequest = OneTimeWorkRequestBuilder<CleanupWorker>()
.build()
workManager
.beginWith(compressRequests) // Parallel
.then(uploadRequest) // Sequential
.then(cleanupRequest) // Sequential
.enqueue()
}Output dari parallel workers digabungkan ke dalam ArrayCreatingInputMerger secara default. Worker berikutnya menerima semua pasangan key-value, dengan array yang dibuat untuk key duplikat.
Siap menguasai wawancara Android Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Menjadwalkan Periodic Work dengan PeriodicWorkRequest
PeriodicWorkRequest dieksekusi berulang dengan interval minimum 15 menit (Android memberlakukan batas ini).
fun scheduleDailySync(context: Context) {
val syncRequest = PeriodicWorkRequestBuilder<SyncWorker>(
repeatInterval = 6,
repeatIntervalTimeUnit = TimeUnit.HOURS,
flexTimeWindow = 30,
flexTimeUnit = TimeUnit.MINUTES
)
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
)
.addTag("periodic_sync")
.build()
WorkManager.getInstance(context)
.enqueueUniquePeriodicWork(
"daily_sync",
ExistingPeriodicWorkPolicy.UPDATE,
syncRequest
)
}Flex window memungkinkan WorkManager untuk mengelompokkan pekerjaan dengan job lain, meningkatkan efisiensi baterai. Interval 6 jam dengan flex 30 menit berarti eksekusi terjadi antara 5:30 dan 6:00 setelah eksekusi sebelumnya.
Mengamati Status Pekerjaan dengan LiveData dan Flow
WorkManager mengekspos status pekerjaan melalui WorkInfo. Amati menggunakan LiveData atau Kotlin Flow.
class UploadViewModel(application: Application) : AndroidViewModel(application) {
private val workManager = WorkManager.getInstance(application)
// Flow-based observation
fun observeUpload(workId: UUID): Flow<WorkInfo?> {
return workManager.getWorkInfoByIdFlow(workId)
}
// Check if any upload is running
val activeUploads: Flow<List<WorkInfo>> =
workManager.getWorkInfosByTagFlow("upload")
.map { workInfos ->
workInfos.filter { it.state == WorkInfo.State.RUNNING }
}
}
// In Compose UI
@Composable
fun UploadProgress(workId: UUID, viewModel: UploadViewModel) {
val workInfo by viewModel.observeUpload(workId)
.collectAsState(initial = null)
when (workInfo?.state) {
WorkInfo.State.RUNNING -> {
val status = workInfo?.progress?.getString("status") ?: "working"
CircularProgressIndicator()
Text(status)
}
WorkInfo.State.SUCCEEDED -> {
val url = workInfo?.outputData?.getString("url")
Text("Uploaded: $url")
}
WorkInfo.State.FAILED -> Text("Upload failed")
else -> {}
}
}Status pekerjaan mengikuti lifecycle: ENQUEUED, RUNNING, SUCCEEDED/FAILED/CANCELLED, BLOCKED (menunggu dependencies).
API Work Metrics WorkManager 2.12
WorkManager 2.12.0-rc01 (Agustus 2026) memperkenalkan WorkMetricsInfo untuk melacak riwayat eksekusi.
class MetricsRepository(private val context: Context) {
private val workManager = WorkManager.getInstance(context)
suspend fun getWorkerMetrics(workerName: String): List<WorkMetricsInfo> {
val query = WorkMetricsQuery.Builder()
.setWorkerClassName(workerName)
.setLimit(100)
.build()
return workManager.getWorkMetrics(query)
}
fun analyzeFailures(metrics: List<WorkMetricsInfo>): Map<Int, Int> {
// Count stop reasons
return metrics
.flatMap { it.stopReasonCounts.entries }
.groupBy { it.key }
.mapValues { entry -> entry.value.sumOf { it.value } }
}
}Metrics mencakup durasi eksekusi, jumlah retry, alasan berhenti, dan timestamp. API ini memungkinkan debugging kegagalan intermiten di production tanpa infrastruktur logging kustom.
Data WorkMetricsInfo dipangkas setelah 7 hari secara default. Konfigurasi retensi dengan Configuration.Builder().setWorkMetricsRetentionDuration().
Menguji Workers dengan WorkManagerTestInitHelper
Unit testing workers memerlukan artifact work-testing. TestListenableWorkerBuilder membuat workers tanpa meng-enqueue mereka.
@RunWith(AndroidJUnit4::class)
class SyncWorkerTest {
private lateinit var context: Context
@Before
fun setup() {
context = ApplicationProvider.getApplicationContext()
val config = Configuration.Builder()
.setMinimumLoggingLevel(Log.DEBUG)
.setExecutor(SynchronousExecutor())
.build()
WorkManagerTestInitHelper.initializeTestWorkManager(context, config)
}
@Test
fun syncWorker_withValidUserId_succeeds() = runTest {
val inputData = workDataOf("user_id" to "123")
val worker = TestListenableWorkerBuilder<SyncWorker>(context)
.setInputData(inputData)
.build()
val result = worker.doWork()
assertThat(result).isEqualTo(ListenableWorker.Result.success())
}
@Test
fun syncWorker_withoutUserId_fails() = runTest {
val worker = TestListenableWorkerBuilder<SyncWorker>(context)
.build()
val result = worker.doWork()
assertThat(result).isEqualTo(ListenableWorker.Result.failure())
}
}Untuk integration tests yang memverifikasi constraints dan chaining, gunakan TestDriver untuk mensimulasikan kepuasan constraint dan perjalanan waktu.
Pertanyaan Interview Umum tentang WorkManager
Interview teknis sering menguji pemahaman tentang jaminan dan trade-off WorkManager. Pertanyaan-pertanyaan ini muncul dalam interview Android level menengah dan senior.
T: Apa yang terjadi pada WorkRequest ketika aplikasi dimatikan?
WorkManager menyimpan work requests dalam database Room. Ketika aplikasi restart atau sistem memberi sinyal bahwa constraint terpenuhi, pekerjaan yang tertunda dilanjutkan. Jaminan ini yang membedakan WorkManager dari pekerjaan CoroutineScope yang mati bersama proses.
T: Bagaimana perbedaan WorkManager dengan AlarmManager?
AlarmManager menjadwalkan alarm dengan waktu yang tepat dan menjalankan kode pada waktu jam tertentu. WorkManager menjadwalkan pekerjaan yang dapat ditunda yang berjalan ketika constraints terpenuhi, tanpa jaminan waktu yang tepat. Gunakan AlarmManager untuk alarm yang menghadap pengguna, WorkManager untuk pemrosesan data background.
T: Bisakah WorkManager menjalankan pekerjaan secara langsung?
Ya, dengan setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST). Expedited work requests menggunakan slot foreground service pada API 31+ atau JobScheduler.setImportantWhileForeground() pada API yang lebih lama. Batas kuota berlaku, jadi OutOfQuotaPolicy mendefinisikan perilaku fallback.
T: Bagaimana cara membatalkan semua pending uploads?
WorkManager.getInstance(context).cancelAllWorkByTag("upload")Tags memungkinkan operasi massal. Alternatifnya, cancelUniqueWork("name") membatalkan chain tertentu.
Menangani System-Induced Stops dengan Backoff Policies
Ketika sistem menghentikan worker (optimisasi baterai, tekanan memori), kebijakan backoff menentukan waktu retry.
val request = OneTimeWorkRequestBuilder<UploadWorker>()
.setBackoffCriteria(
BackoffPolicy.EXPONENTIAL,
Duration.ofSeconds(30) // Initial delay, minimum 10 seconds
)
.setBackoffOnSystemInterruption(true) // New in 2.11
.build()Exponential backoff menggandakan delay pada setiap retry: 30s, 60s, 120s, hingga maksimum 5 jam. Linear backoff menambahkan delay awal setiap kali: 30s, 60s, 90s. Flag setBackoffOnSystemInterruption() yang baru di WorkManager 2.11 menerapkan backoff bahkan ketika sistem (bukan worker) yang menyebabkan berhenti.
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Poin-Poin Penting untuk Penggunaan WorkManager di Production
- Utamakan
CoroutineWorkerdaripadaWorkersaat memanggil suspend functions. Ini menghindari pemblokiran thread dan terintegrasi dengan kode coroutine yang ada. - Gunakan
enqueueUniqueWork()untuk mencegah pekerjaan duplikat. PilihKEEPuntuk operasi idempoten,REPLACEketika hanya permintaan terbaru yang penting. - Tetapkan tag yang bermakna pada setiap request. Tags memungkinkan observasi, pembatalan, dan debugging di seluruh work chains.
- Uji workers secara terisolasi dengan
TestListenableWorkerBuilder, kemudian uji chains dengan simulasi constraintTestDriver. - API
WorkMetricsInfoWorkManager 2.12 menyediakan riwayat eksekusi. Gunakan untuk debug pola retry dan alasan berhenti di production. - Constraints menghemat baterai. Worker yang gagal karena tidak ada jaringan membuang siklus CPU dan menguras daya pada percobaan retry.
- Minimum 15 menit untuk periodic work diberlakukan oleh Android, bukan WorkManager. Rancang tugas periodik untuk menoleransi interval ini.
Bisakah kamu menemukan bug di Android?
Satu potongan kode nyata, satu bug tersembunyi, satu percobaan per hari. Tanpa akun untuk mencoba.

Ditulis oleh
Anthony Fillion-MailletPendiri SharpSkill
Developer fullstack selama lebih dari 10 tahun. Ia menjalankan SharpSkill dan bertanggung jawab atas semua yang diterbitkan di sini.
Diperbarui 22 Agustus 2026
Bagikan
Artikel terkait

Modularisasi Android 2026: Arsitektur Multi-Modul dan Pertanyaan Interview
Kuasai arsitektur multi-modul Android dengan convention plugins, Gradle version catalogs, dan feature modules. Termasuk pertanyaan interview umum tentang strategi modularisasi.

Android CameraX 2026: Panduan Lengkap Pengambilan Foto dan Video dengan Pertanyaan Wawancara
Pelajari CameraX di Android 2026: pengambilan foto, perekaman video, integrasi Jetpack Compose, dan pertanyaan wawancara teknis untuk developer Android.

Jetpack Navigation Compose 2026: Navigasi Type-Safe dan Pertanyaan Interview
Pelajari Jetpack Navigation Compose 2.10 dengan navigasi type-safe menggunakan Kotlin Serialization. Panduan lengkap dengan contoh kode dan pertanyaan interview Android.