← Back to list

WorkManager

Android’de bazı işlemler vardır ki kesintisiz ve garantiye yakın şekilde çalışması gerekir. İşte bu noktada WorkManager devreye girer.

deniz baş · 2026-05-01 13:36 · 0 claps · 3.3 min read
#kotlin #workmanager #hilts #kotlin-coroutines
Open on Medium ↗
Wiki topics: 📱 · Mobile Development 🎮 · Gaming

WorkManager

Android’de bazı işlemler vardır ki kesintisiz ve garantiye yakın şekilde çalışması gerekir. İşte bu noktada WorkManager devreye girer.

WorkManager, Android Jetpack kütüphanesinin bir parçasıdır ve özellikle aşağıdaki senaryolar için idealdir:

  • Uygulama kapansa bile çalışması gereken işler
  • Cihaz yeniden başlasa bile devam etmesi gereken işlemler
  • Network sonradan geldiğinde tetiklenmesi gereken görevler

Ne zaman kullanılır?

WorkManager genellikle şu işlemler için tercih edilir:

  • Log gönderme
  • Veri senkronizasyonu
  • Fotoğraf upload etme
  • Cache temizleme

Kullanılan Teknolojiler

Bu örnekte aşağıdaki bileşenleri birlikte kullanacağız:

  • Hilt → Dependency Injection
  • ViewModel → Lifecycle-aware state yönetimi
  • Kotlin Coroutines → Asenkron işlemler
  • WorkManager → Garantili background tasks

Dependency Kurulumu

// root build.gradle (project-level)
plugins {
    id("com.google.dagger.hilt.android") version "2.51.1" apply false
}
// app/build.gradle.kts
plugins {
    id("com.google.dagger.hilt.android")
    id("kotlin-kapt")
}
dependencies {
    // Hilt
    implementation("com.google.dagger:hilt-android:2.51.1")
    kapt("com.google.dagger:hilt-compiler:2.51.1")
    // ViewModel + Compose
    implementation("androidx.hilt:hilt-navigation-compose:1.2.0")
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7")
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7")
    // Coroutines
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1")
    // WorkManager
    implementation("androidx.work:work-runtime-ktx:2.9.0")
    // Hilt + WorkManager
    implementation("androidx.hilt:hilt-work:1.2.0")
    kapt("androidx.hilt:hilt-compiler:1.2.0")
}
// project-level (alternatif kullanım)
buildscript {
    dependencies {
        classpath("com.google.dagger:hilt-android-gradle-plugin:2.51.1")
    }
}

Mimari Yaklaşım

Bu örnekte WorkManager tetikleme işlemini ViewModel üzerinden yöneteceğiz.

Bunun için:

  1. SyncScheduler adında bir interface oluşturacağız
  2. Bunun implementasyonu olan SyncSchedulerImpl ile WorkManager işlemini başlatacağız

SyncScheduler Implementasyonu

interface SyncScheduler {
    fun scheduleOneTimeSync()
}
class SyncSchedulerImpl @Inject constructor(
    @ApplicationContext private val context: Context
) : SyncScheduler {
    override fun scheduleOneTimeSync() {
        val request = OneTimeWorkRequestBuilder<SyncWorker>()
            .setConstraints(
                Constraints.Builder()
                    .setRequiredNetworkType(NetworkType.CONNECTED)
                    .build()
            )
            .setBackoffCriteria(
                BackoffPolicy.EXPONENTIAL,
                30,
                TimeUnit.SECONDS
            )
            .build()
        WorkManager.getInstance(context).enqueueUniqueWork(
            "sync_work",
            ExistingWorkPolicy.KEEP,
            request
        )
    }
}

Önemli Noktalar

1. Network Constraint

setRequiredNetworkType(NetworkType.CONNECTED)

Bu ayar sayesinde:

  • İş sadece internet bağlantısı varsa çalışır
  • Network sonradan gelirse otomatik olarak tetiklenir

2. Retry Mekanizması (Backoff)

setBackoffCriteria(
    BackoffPolicy.EXPONENTIAL,
    30,
    TimeUnit.SECONDS
)

Bu yapı, iş başarısız olduğunda tekrar deneme stratejisini belirler.

EXPONENTIAL:

  • 30 sn
  • 60 sn
  • 120 sn
  • 240 sn

Fail durumunda süre katlanarak artar.

LINEAR:

  • 30 sn
  • 60 sn
  • 90 sn
  • 120 sn

Fail durumunda süre sabit artışla ilerler.

3. Küçük ama önemli detay

Buradaki 30 saniye değeri:

  • İlk retry için bekleme süresidir
  • İlk çalışmayı etkilemez

Kritik Nokta: Duplicate Work Problemi

enqueueUniqueWork(...)

Eğer bunu kullanmazsan:

👉 Aynı iş birden fazla kez enqueue edilir 👉 Arka planda gereksiz duplicate işlemler oluşur

Bu yüzden production’da unique work kullanmak kritik.

Repository Örneği

Worker içinde kullanmak için basit bir repository:

class SyncRepository @Inject constructor() {
    suspend fun syncData() {
        Log.d("SyncWorker","SyncRepository syncData working...")
    }
}

Worker Implementasyonu

@HiltWorker
class SyncWorker @AssistedInject constructor(
    @Assisted context: Context,
    @Assisted parameters: WorkerParameters,
    private val syncRepository: SyncRepository
) : CoroutineWorker(context, parameters) {
    override suspend fun doWork(): Result {
            return try {
                Log.d("SyncWorker", "SyncWorker worked...")
                syncRepository.syncData()
                Result.success()
            } catch (e: Exception) {
                Log.d("SyncWorker", "SyncWorker did not work...$e")
                Result.retry()
            }
        }
    }

Açıklamalar

  • @HiltWorker → Bu class’ın Hilt tarafından oluşturulacağını belirtir
  • @AssistedInject → Bazı parametrelerin (Context, WorkerParameters) sistem tarafından verileceğini ifade eder
  • SyncRepository → Hilt tarafından inject edilir
  • CoroutineWorker -> CoroutineWorker kullanırız çünkü suspend fonksiyonları direkt kullanabiliriz. Blocking thread kullanmaz.

Gelişmiş Hata Yönetimi

override suspend fun doWork(): Result {
    return try {
        syncRepository.syncData()
        Result.success()
    } catch (e: IOException) {
        Result.retry()
    } catch (e: HttpException) {
        if (e.code() >= 500) {
            Result.retry()
        } else {
            Result.failure()
        }
    } catch (e: Exception) {
        Result.failure()
    }
}
  • Network hatası → retry
  • Server error → retry
  • Client error → failure

Önemli Hata

SyncWorker sınıfına context, parameters ve syncRepository olmak üzere 3 adet parametre ekledik. Ancak CoroutineWorkers ile sadece context ve parameters alıyoruz. Bu tarz bir kullanımda aşağıdaki hata alıancaktr.

NoSuchMethodException: SyncWorker.<init>(Context, WorkerParameters)

Sebebi: WorkManager default olarak sadece bu iki parametreyi bekler. Bu hatanın çözümlenebilmesi için kendimize ait bir CustomWorkManager tanımlamamız gerekiyor.

CustomWorkerManager

class CustomWorkManager(
    private val syncRepository: SyncRepository
) : WorkerFactory() {
override fun createWorker(
        appContext: Context,
        workerClassName: String,
        workerParameters: WorkerParameters
    ): ListenableWorker? {
        return SyncWorker(appContext, workerParameters, syncRepository)
    }
}

Application Config

Oluşturdumuz SyncWorker sınıfında appContext ve workerParameters haricinde ekstra bir parametre olsun yada olmasın fark etmez, WorkManager çalışması için bu eklemenin @HiltAndroidApp annotation’ı eklenmiş Application sınıfınada eklenmesi gerekmektedir.

@HiltAndroidApp
class MyApplication : Application(), Configuration.Provider {

    @Inject
    lateinit var syncRepository: SyncRepository

    override val workManagerConfiguration: Configuration
        get() = Configuration.Builder()
            .setMinimumLoggingLevel(Log.DEBUG)
            .setWorkerFactory(CustomWorkManager(syncRepository))
            .build()
}

Eğerki SyncWorker sınıfımız ekstra bir parametre almıyorsa setWorkerFactory içerisine sadece workerFactory ekleriz. Eğerki ekstra bir parametre alıyor ise CustomWorkManager(syncRepository) ekleriz. Eğer SyncWorker bir parametre alıyorsa sınıf içerisinden HiltWorkerFactory’yi silmemiz gerekir.

  • @HiltAndroidApp -> Hilt’in giriş noktasıdır. Uygulama ayağa kalkarken dependency graph oluşturulur ve tüm inject işlemleri buradan başlar.
  • Configuration.Provider -> Configuration.Provider ile WorkManager config yapısını manuel olarak veririz.
  • HiltWorkerFactory -> @HiltWorker ile oluşturulan (Örnek:SyncWorker) worker’ları üretir.

Manifest Ayarı

<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">
    <meta-data
        android:name="androidx.work.WorkManagerInitializer"
        android:value="androidx.startup"
        tools:node="remove" />
</provider>

Hilt Module

Hilt tarafında SyncRepository kullanmak için SyncRepository module içerisine eklenmeli.

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
    @Singleton
    fun provideSyncRepository(): SyncRepository {
        return SyncRepository()
    }
}

ViewModel içerisinden SyncScheduler çağırılır ve kullanıma başlanır.

@HiltViewModel
class MainViewModel @Inject constructor(
    private val syncScheduler: SyncScheduler
): ViewModel() {

    fun onSyncClicked() {
        syncScheduler.scheduleOneTimeSync()
    }

}

Sonuç

WorkManager:

  • Uygulama kapalı olsa bile çalışır
  • Network geldiğinde tetiklenir
  • Retry mekanizması vardır
  • Doğru kullanıldığında production için oldukça güvenlidir

Özellikle:

  • Sync işlemleri
  • Background veri gönderimi
  • Kritik görevler

için vazgeçilmezdir.


메타데이터
post_id
769ef4d10538
slug
workmanager-769ef4d10538
url
https://medium.com/@denizbas92/workmanager-769ef4d10538
canonical_url
https://medium.com/@denizbas92/workmanager-769ef4d10538
author_url
https://medium.com/@denizbas92
status
ok
fetched_at
2026-06-24 04:09:36