Dagger / Hilt: nedir, DI ve uygulama

Yazar: IT Sectr Yayınlanma: 2026-05-03 Okuma süresi: 9 dk

Dagger, Java ve Kotlin için, anotasyon işleme yoluyla derleme zamanında DI kodu üreten bir bağımlılık enjeksiyonu çerçevesidir. Hilt, Android için Dagger üzerine bir sarmalayıcıdır ve bileşen kurulumunu ve yaşam döngüsü yönetimini basitleştirir. Google, 2025'e göre Hilt, Google Play Top-100'deki Android uygulamalarının %70'inden fazlasında kullanılmakta olup, önceden tanımlanmış bileşenler aracılığıyla Activity, Fragment, ViewModel ve Service'i destekler. Her iki çerçeve de derleme zamanında bağımlılık grafiği doğrulaması sağlayarak çalışma zamanı enjeksiyon hatalarını ortadan kaldırır.

Önemli Noktalar

  • Dagger — @Module, @Provides, @Component anotasyonları aracılığıyla kod üretimi ile derleme zamanı DI çerçevesi
  • Hilt — @HiltAndroidApp, @AndroidEntryPoint, @HiltViewModel aracılığıyla Dagger'ı basitleştiren Android sarmalayıcısı
  • Component — Proxy yöntemler aracılığıyla Module'ü Inject hedeflerine bağlayan bağımlılık grafiği
  • Scope — @Singleton, @ViewModelScoped, @ActivityScoped enjekte edilen nesnelerin ömrünü yönetir
  • Hilt, izole bağımlılık grafikleri için @InstallIn aracılığıyla çok modüllü projeleri destekler

Dagger / Hilt Nedir?

Dagger, derleme zamanı kod üretimine sahip bir bağımlılık enjeksiyonu çerçevesidir. Başlangıçta Square'de geliştirilmiş ve daha sonra Google'a devredilmiş olan Dagger, bağımlılık grafiğini analiz etmek ve fabrika sınıfları oluşturmak için Java APT anotasyon işlemcisini kullanır. Çalışma zamanı DI'dan (Guice, Koin) farklı olarak Dagger, yansıma kullanmaz — tüm kod derleme zamanında oluşturulur, çalışma zamanında maksimum performans ve derleme zamanında hata tespiti sağlar.

Hilt, Dagger üzerine inşa edilmiş ve Android için optimize edilmiş bir Google kütüphanesidir. Hilt, Android bileşen yaşam döngüsüne karşılık gelen önceden tanımlanmış bileşenler sağlar: Application için @SingletonComponent, Activity için @ActivityComponent, Fragment için @FragmentComponent, ViewModel için @ViewModelComponent. Bu, saf Dagger'da gereken rutin Component ve Module yapılandırmasını ortadan kaldırır. Hilt ayrıca @AndroidEntryPoint aracılığıyla her Android bileşeni için bağımlılık grafiğini otomatik olarak oluşturur.

Google I/O 2024'e göre Hilt, Kotlin ile yazılmış Android uygulamalarında DI için önerilen çözümdür. Jetpack kütüphaneleri (Navigation, Room, WorkManager), @HiltViewModel ve @HiltWorker aracılığıyla Hilt ile yerleşik entegrasyona sahiptir. Android kullanmayan projelerde (saf Java/Kotlin kütüphaneleri, sunucu uygulamaları), Hilt sarmalayıcısı olmadan saf Dagger kullanılır.

Manuel Bağımlılık Enjeksiyonunun Sorunu

Bir DI çerçevesi olmadan, geliştirici nesneleri manuel olarak yapıcılar veya fabrikalar aracılığıyla oluşturur ve bağımlılıkları zincir boyunca iletir. Her yeni gereksinim, zincirdeki tüm yapıcıların imzalarını değiştirmek anlamına gelir. Dagger bu süreci otomatikleştirir: sadece hangi türün gerektiğini bildirirsiniz (@Inject constructor) ve Dagger, tüm iç içe türleri çözerek bağımlılık grafiğini oluşturur. Bağımlılıklar değiştiğinde, Dagger oluşturulan kodu otomatik olarak günceller — zincirde hata yapmak imkansızdır.

Bağımlılık Enjeksiyonunun İlkeleri

Bağımlılık Enjeksiyonu, bir nesnenin bağımlılıklarını kendisinin oluşturması yerine dışarıdan aldığı bir desendir. DI, Kontrolün Tersine Çevrilmesi (IoC) ilkesini uygular: bir sınıf, kendi bağımlılıklarını oluşturmaktan sorumlu değildir, bunun yerine bunları bir yapıcı, yöntem veya alan aracılığıyla bildirir. Yapıcı enjeksiyonu, nesnenin geçerli bir durumda oluşturulmasını garanti ettiği için en çok tercih edilen yöntemdir.

Enjeksiyon TürüDagger SözdizimiNe Zaman Kullanılır
Constructor injection@Inject constructorBirincil yöntem — tüm özel sınıflar için
Field injection@Inject lateinit varSadece Android bileşenleri için (Activity, Fragment)
Method injection@Inject fun bind()Oluşturma sonrası başlatma için

Derleme Zamanı DI'ın Avantajları

DI'ın başlıca avantajları arasında test edilebilirlik (bağımlılıklar mock nesnelerle değiştirilebilir), gevşek bağlantı (sınıflar uygulamalara değil arayüzlere bağlıdır) ve kapsamlar aracılığıyla nesnelerin açık yaşam döngüsü yönetimi bulunur. Dagger, bir nesnenin kapsamı dahilinde bir kez oluşturulmasını ve kapsamdan çıkıldığında yok edilmesini otomatik olarak garanti eder.

Dagger Mimarisi: Component, Module, Provides

Component, Dagger bağımlılık grafiğinin merkezi öğesidir. @Component ile işaretlenmiş bir arayüzdür ve Module ile enjeksiyon hedefleri arasındaki köprüyü tanımlar. Dagger, derleme zamanında Component uygulamasını (örneğin DaggerAppComponent) oluşturur. Component, gerekli türleri döndüren soyut yöntemler veya alan enjeksiyonu için bir nesne kabul eden inject yöntemleri aracılığıyla enjeksiyon için hangi türlerin kullanılabilir olduğunu belirler.

kotlin
// Module: Dagger'ın kendi başına oluşturamadığı bağımlılıkları sağlar
@Module
class NetworkModule {
    @Provides
    @Singleton
    fun provideOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .build()
    }

    @Provides
    @Singleton
    fun provideApiService(client: OkHttpClient): ApiService {
        return Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(ApiService::class.java)
    }
}

// Component: Module'ü ve Injection hedeflerini bağlar
@Component(modules = [NetworkModule::class])
interface AppComponent {
    fun inject(activity: MainActivity)
    fun getApiService(): ApiService
}

@Module, @Provides ile bağımlılık örneklerini döndüren yöntemler içeren bir sınıftır. Module, Dagger'ın otomatik olarak oluşturamadığı türler için kullanılır: üçüncü taraf kütüphaneler (OkHttp, Retrofit), yapıcı parametreleri olan nesneler, uygulama seçimi olan arayüzler. @Binds, bir yöntemin bir arayüz döndürdüğü ve tek bir uygulamayı kabul ettiği durumlarda @Provides'a bir alternatiftir: Dagger, yöntemi çağırmadan doğrudan dönüşüm oluşturur.

@Scope, bağımlılık grafiğindeki bir nesnenin ömrünü tanımlar. @Singleton — nesne tüm uygulama için bir kez oluşturulur. @ActivityScoped — nesne, Activity yaşadığı sürece yaşar. @FragmentScoped — Fragment yaşadığı sürece. Kapsam olmadan, Dagger her enjeksiyonda yeni bir örnek oluşturur. @Reusable — tekil olması gerekmeyen ancak oluşturulması pahalı olan nesneler için bir kapsam — Dagger örneği önbelleğe alabilir ancak garanti etmez.

Android için Hilt: @HiltAndroidApp ve @AndroidEntryPoint

Hilt, önceden tanımlanmış bileşenler ve otomatik temel grafik oluşturma yoluyla Android için Dagger yapılandırmasını basitleştirir. Application sınıfındaki @HiltAndroidApp anotasyonu, Hilt bileşeni oluşturmayı tetikler. Bu anotasyon olmadan Hilt çalışmaz — Hilt kullanan herhangi bir Android uygulaması için zorunludur. @HiltAndroidApp, uygulamanın diğer tüm bileşenlerinin miras aldığı üst SingletonComponent'i oluşturur.

kotlin
@HiltAndroidApp
class MyApplication : Application()

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject lateinit var apiService: ApiService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // apiService, onCreate çağrısından önce zaten enjekte edildi
    }
}

@Module
@InstallIn(SingletonComponent::class)
class AppModule {
    @Provides
    @Singleton
    fun provideDatabase(@ApplicationContext ctx: Context): AppDatabase {
        return Room.databaseBuilder(ctx, AppDatabase::class.java, "app.db").build()
    }
}

@AndroidEntryPoint, Activity, Fragment, Service, BroadcastReceiver ve View için bir anotasyondur. Her tür için bir Hilt bileşeni oluşturur: Bir Activity'de @AndroidEntryPoint, SingletonComponent'ten miras alan bir ActivityComponent oluşturur. Alt bileşen, otomatik olarak üst bileşenin tüm bağımlılıklarını alır. @Inject lateinit var ile alan enjeksiyonu yalnızca @AndroidEntryPoint ile işaretlenmiş sınıflarda kullanılabilir — normal sınıflarda yapıcı enjeksiyonu kullanılır.

@InstallIn, bir modülün hangi Hilt bileşenine kurulacağını belirtir. @InstallIn(SingletonComponent::class) ile NetworkModule, uygulama genelinde kullanılabilir. @InstallIn(ActivityComponent::class) ile bir Module yalnızca Activity'de kullanılabilir. Bu, bağımlılık grafiklerini izole eder: Activity'ye özgü modüller Fragment ve ViewModel'de görünmez, geçersiz bağımlılıkların yanlışlıkla kullanılmasını önler. @ApplicationContext, uygulama Context'ini almak için Hilt'in yerleşik niteleyicisidir.

Qualifier: @Named ve Özel Niteleyiciler

Aynı arayüzün iki farklı uygulamasının enjekte edilmesi gerektiğinde, niteleyiciler kullanılır. Hilt, dize tanımlayıcıları için @Named'i ve @Qualifier ile özel anotasyonları destekler. Örneğin, farklı dize yapılandırmaları için @Named("baseUrl") ve @Named("imageBaseUrl"). Özel niteleyiciler, derleme zamanı denetimi sayesinde @Named'e tercih edilir — yanlış bir dize adı çalışma zamanına kadar tespit edilmez.

Hilt ViewModel: @HiltViewModel ve @Inject constructor

@HiltViewModel, manuel ViewModelProvider.Factory'nin yerini alan bir anotasyondur. @HiltViewModel ile işaretlenmiş ve @Inject constructor'a sahip bir sınıf, Dagger aracılığıyla otomatik olarak tüm bağımlılıkları alır. Hilt, Jetpack ViewModelProvider tarafından kullanılan bir ViewModelFactory oluşturur. Hilt olmadan, geliştiricinin her parametreyi Activity veya fragment'tan geçirerek fabrikayı manuel olarak yazması gerekir.

kotlin
@HiltViewModel
class MainViewModel
    @Inject constructor(
        private val apiService: ApiService,
        private val database: AppDatabase
    ) : ViewModel() {

    private val _users = MutableStateFlow<List<User>>(emptyList())
    val users: StateFlow<List<User>> = _users.asStateFlow()

    fun loadUsers() {
        viewModelScope.launch {
            _users.value = apiService.getUsers()
        }
    }
}

// Activity'de — Hilt otomatik olarak ViewModel oluşturur
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by viewModels()
}

ViewModelScoped, ViewModel yaşadığı sürece bağımlılıkların yaşadığı bir Hilt kapsamıdır. Aynı türden iki ViewModel aynı @ViewModelScoped bağımlılığını enjekte ederse, her biri kendi örneğini alır. Bu, @ViewModelScoped'u @ActivityScoped'ten ayırır; burada bir Activity, tüm fragment'lar için bir örnek alır. ViewModel'e özgü bağımlılıklar (örneğin SavedStateHandle) için @HiltViewModel, @Inject constructor(savedStateHandle: SavedStateHandle) ile kullanılır.

Hilt, Hilt Extensions kütüphanesi aracılığıyla yardımlı enjeksiyonu destekler. Yardımlı enjeksiyon, bazı bağımlılıkların yalnızca çalışma zamanında bilindiği durumlarda (örneğin, bir intent'ten kullanıcı kimliği) enjeksiyon sırasında yapıcıya parametrelerin iletilmesine olanak tanır. Yardımlı enjeksiyon için @AssistedInject, @Assisted parametreleriyle birlikte kullanılır. Hilt, standart şekilde enjekte edilebilen bir AssistedFactory oluşturur.

Dagger vs Hilt: Karşılaştırma ve Geçiş

Saf Dagger, Component'in manuel olarak oluşturulmasını, kapsamların tanımlanmasını ve her Android bileşenine enjeksiyon yapılandırmasını gerektirir. Geliştirici AppComponent, ActivityComponent, FragmentComponent oluşturur ve @Subcomponent aracılığıyla ilişkilerini yönetir. Bu yaklaşım maksimum kontrol sağlar ancak önemli miktarda kalıp kod (boilerplate) gerektirir. Dagger, standart olmayan DI mimarisi gerektiren büyük projelerde veya Android olmayan Java/Kotlin projelerinde kullanılır.

Hilt kalıp kodu otomatikleştirir: bir @HiltAndroidApp, her bileşen için bir @AndroidEntryPoint, önceden tanımlanmış kapsamlar. Google, tüm yeni Android projeleri için Hilt'i önermektedir. Dagger'dan Hilt'e geçiş, Component'in @InstallIn ile değiştirilmesini, @Subcomponent'in önceden tanımlanmış Hilt bileşenleriyle değiştirilmesini ve manuel ViewModelProvider.Factory'nin @HiltViewModel ile değiştirilmesini içerir. Çoğu @Module sınıfı, @Provides yöntemlerini değiştirmeden @InstallIn eklenerek taşınır.

ÖzellikDaggerHilt
KurulumManuel: Component, Subcomponent, BuilderOtomatik: @HiltAndroidApp, @AndroidEntryPoint
Android bileşenleriÖnceden tanımlı yok12+ yerleşik bileşen
ViewModelManuel fabrika@HiltViewModel + @Inject constructor
Çok modüllü@Component(dependencies) aracılığıyla@InstallIn + toplama aracılığıyla
KarmaşıklıkYüksek — deneyim gerekliDüşük — sezgisel olarak anlaşılır
EsneklikMaksimumStandart (senaryoların %95'ini kapsar)

Hilt'in sınırlamaları: kütüphane yalnızca Android'i destekler (saf sunucu tarafı Java projeleri için uygun değildir), belirli bir bileşen yapısı dayatır (geçersiz kılması zor) ve Jetpack Compose projeleri için android.hilt:hilt-navigation-compose bağımlılığı ekler. Compose uygulamaları için Hilt, Composable içinde hiltViewModel() aracılığıyla erişilebilen @HiltViewModel sağlar — Activity'den manuel ViewModel sağlama gerekmez.

Sıkça Sorulan Sorular

Dagger ve Hilt arasındaki fark nedir?

Dagger, manuel Component ve Module yapılandırmasına sahip temel bir derleme zamanı DI çerçevesidir. Hilt, bileşen oluşturmayı ve Activity, Fragment, ViewModel, Service ve BroadcastReceiver'ın yaşam döngüsüyle entegrasyonu otomatikleştiren bir Android sarmalayıcısıdır.

@HiltAndroidApp neden gereklidir?

@HiltAndroidApp, Application için Hilt bileşeni oluşturmayı etkinleştirir. Bu anotasyon olmadan Hilt, tüm ActivityComponent, FragmentComponent ve ViewModelComponent'in miras aldığı temel SingletonComponent'i oluşturamaz. Anotasyon her Hilt projesi için zorunludur.

Hilt, Jetpack Navigation ile nasıl çalışır?

Hilt Navigation, NavBackStackEntry içindeki ViewModel için @HiltViewModel ve navigasyon grafiği içinde ViewModel'i kapsamlamak için hiltNavGraphViewModels() sağlar. android.hilt:hilt-navigation-fragment kütüphanesi, her NavBackStackEntry için otomatik olarak bir ViewModel oluşturur.

Hilt'te Context nasıl enjekte edilir?

Uygulama bağlamı için @ApplicationContext veya Activity bağlamı için @ActivityContext kullanın. Hilt, bu niteleyicileri android.hilt:hilt-android kütüphanesinde yerleşik olarak sağlar. @ActivityContext yalnızca ActivityComponent'te kurulu modüllerde kullanılabilir.

@Binds nedir ve ne zaman kullanılır?

@Binds, bir yöntemin tam olarak bir parametre kabul ettiği ve türünü bir arayüz olarak döndürdüğü durumlarda @Provides'a verimli bir alternatiftir. @Binds, yöntemi çağırmadan doğrudan dönüşüm oluşturur, oluşturulan kod miktarını azaltır ve enjeksiyon performansını artırır.

Özet

  • Dagger — @Module, @Provides, @Component anotasyonları ve APT aracılığıyla kod üretimi ile derleme zamanı DI çerçevesi
  • Hilt — @HiltAndroidApp, @AndroidEntryPoint, @InstallIn ve önceden tanımlanmış bileşenlerle Dagger üzerinde Android sarmalayıcısı
  • Component bağımlılık grafiğini yönetir, Module üçüncü taraf sınıfları sağlar, Provides nesne fabrikaları sağlar
  • Scope (@Singleton, @ViewModelScoped, @ActivityScoped) Dagger grafiğinde nesne ömrünü tanımlar
  • @HiltViewModel ViewModel oluşturmayı otomatikleştirir, manuel ViewModelProvider.Factory fabrikalarını ortadan kaldırır
  • @InstallIn modülleri bileşenlere göre izole eder, uygulama katmanları arasında bağımlılık sızıntısını önler
  • Hilt, Google tarafından tüm yeni Android projeleri için önerilir, Dagger Android olmayan ve özel DI mimarileri için

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun