Dagger — Java və Kotlin üçün asılılıq enjeksiyonu çərçivəsidir, annotasiyaların işlənməsi yolu ilə kompilasiya mərhələsində DI kodu yaradır. Hilt — Android üçün Dagger üzərində qurulmuş əlavədir, komponentlərin və həyat dövrünün konfiqurasiyasını asanlaşdırır. Google, 2025 məlumatlarına görə, Hilt Google Play Top-100-dəki Android tətbiqlərinin 70%-dən çoxunda istifadə olunur, Activity, Fragment, ViewModel və Service-i əvvəlcədən təyin edilmiş komponentlər vasitəsilə dəstəkləyir. Hər iki çərçivə asılılıq qrafının kompilasiya vaxtı yoxlanılmasını təmin edərək, icra vaxtı enjeksiyon xətalarını aradan qaldırır.
Əsas məqamlar
Dagger — kompilasiya mərhələsində kod yaradan asılılıq enjeksiyonu çərçivəsidir (compile-time DI). Square-də hazırlanmış və sonra Google-a verilmiş Dagger, asılılıq qrafını təhlil etmək və fabrik sinifləri yaratmaq üçün Java APT annotasiya prosessorundan istifadə edir. Runtime-DI-dən (Guice, Koin) fərqli olaraq, Dagger reflektivdən istifadə etmir — bütün kod kompilasiya zamanı yaradılır, bu da icra zamanı maksimum performansı və qurma mərhələsində xətaların aşkarlanmasını təmin edir.
Hilt — Google-dan Dagger əsasında qurulmuş və Android üçün optimallaşdırılmış kitabxanadır. Hilt Android komponentlərinin həyat dövrünə uyğun əvvəlcədən təyin edilmiş komponentlər təqdim edir: Application üçün @SingletonComponent, Activity üçün @ActivityComponent, Fragment üçün @FragmentComponent, ViewModel üçün @ViewModelComponent. Bu, təmiz Dagger-da tələb olunan Component və Module-in rutin konfiqurasiyasını aradan qaldırır. Hilt həmçinin @AndroidEntryPoint vasitəsilə hər bir Android komponenti üçün avtomatik olaraq asılılıq qrafı yaradır.
Google I/O 2024 məlumatlarına görə, Hilt Kotlin-də yazılmış Android tətbiqləri üçün tövsiyə olunan DI həllidir. Jetpack kitabxanaları (Navigation, Room, WorkManager) @HiltViewModel və @HiltWorker vasitəsilə Hilt ilə daxili inteqrasiyaya malikdir. Android istifadə etməyən layihələrdə (təmiz Java/Kotlin kitabxanaları, server tətbiqləri) Hilt əlavəsi olmadan təmiz Dagger tətbiq olunur.
DI çərçivəsi olmadan proqramçı obyektləri əl ilə konstruktorlar və ya fabriklər vasitəsilə yaradır, asılılıqları zəncir boyunca ötürür. Hər yeni tələb — zəncirdəki bütün konstruktorların imzasının dəyişdirilməsi. Dagger bu prosesi avtomatlaşdırır: hansı tipin tələb olunduğunu bəyan etmək kifayətdir (@Inject constructor), və Dagger bütün iç-içə tipləri həll edərək asılılıq qrafı yaradacaq. Asılılıqlar dəyişdikdə Dagger yaradılmış kodu avtomatik yeniləyir — zəncirdə səhv etmək mümkün deyil.
Asılılıq enjeksiyonu (Dependency Injection) — obyektin asılılıqlarını xaricdən aldığı, özü yaratmadığı nümunədir. DI idarəetmənin tərsinə çevrilməsi (IoC) prinsipini həyata keçirir: sinif öz asılılıqlarını yaratmağa görə məsuliyyət daşımır, onları konstruktor, metod və ya sahə vasitəsilə bəyan edir. Konstruktor vasitəsilə enjeksiya (constructor injection) ən üstün hesab olunur, çünki obyektin düzgün vəziyyətdə yaradılmasını təmin edir.
| Enjeksiya növü | Dagger sintaksisi | Nə zaman istifadə olunur |
|---|---|---|
| Constructor injection | @Inject constructor | Əsas üsul — bütün öz sinifləri üçün |
| Field injection | @Inject lateinit var | Yalnız Android komponentləri üçün (Activity, Fragment) |
| Method injection | @Inject fun bind() | Post-construct inisializasiyası üçün |
DI-nin əsas üstünlüklərinə test edilə bilmə (asılılıqlar mock-obyektlər vasitəsilə əvəz oluna bilər), zəif bağlılıq (siniflər reallaşdırmalardan deyil, interfeyslərdən asılıdır) və scopes vasitəsilə obyektlərin həyat dövrünün aşkar idarə edilməsi daxildir. Dagger avtomatik olaraq obyektin öz scope-u çərçivəsində bir dəfə yaradılmasını və scope-dan çıxdıqda məhv edilməsini təmin edir.
Component — Dagger asılılıq qrafının mərkəzi elementidir. Bu, Module ilə enjeksiya hədəfləri arasında körpünü təsvir edən @Component ilə annotasiya olunmuş interfeysdir. Dagger kompilasiya mərhələsində Component-in reallaşdırmasını (məsələn, DaggerAppComponent) yaradır. Component, abstrakt metodlar vasitəsilə tələb olunan tipləri qaytarmaqla və ya field injection üçün obyekt qəbul edən inject metodları vasitəsilə hansı tiplərin enjeksiya üçün mövcud olduğunu müəyyən edir.
// Modul: Dagger-in özü yarada bilmədiyi asılılıqları təmin edir
@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)
}
}
// Komponent: Module və enjeksiya hədəflərini birləşdirir
@Component(modules = [NetworkModule::class])
interface AppComponent {
fun inject(activity: MainActivity)
fun getApiService(): ApiService
}
@Module — asılılıq nümunələrini qaytaran @Provides metodları olan sinifdir. Module Dagger-in avtomatik yarada bilmədiyi tiplər üçün istifadə olunur: üçüncü tərəf kitabxanaları (OkHttp, Retrofit), konstruktor parametrləri olan obyektlər, reallaşdırma seçimi olan interfeyslər. @Binds — metod interfeys qaytardıqda və tək reallaşdırma qəbul etdikdə @Provides üçün alternativdir: Dagger metodu çağırmadan birbaşa cast yaradır.
@Scope obyektin asılılıq qrafında həyat müddətini müəyyən edir. @Singleton — obyekt bütün tətbiq üçün bir dəfə yaradılır. @ActivityScoped — obyekt Activity yaşadıqca yaşayır. @FragmentScoped — Fragment yaşadıqca yaşayır. Scope olmadan Dagger hər enjeksiyada yeni nümunə yaradır. @Reusable — singleton olmaq məcburiyyətində olmayan, lakin yaradılması bahalı olan obyektlər üçün scope-dur — Dagger nümunəni keşləyə bilər, lakin buna zəmanət vermir.
Hilt əvvəlcədən təyin edilmiş komponentlər və əsas qrafın avtomatik yaradılması sayəsində Android üçün Dagger konfiqurasiyasını asanlaşdırır. Application sinfində @HiltAndroidApp annotasiyası Hilt komponentinin yaradılmasını işə salır. Bu annotasiya olmadan Hilt işləmir — Hilt istifadə edən hər bir Android tətbiqi üçün məcburidir. @HiltAndroidApp, bütün digər tətbiq komponentlərinin miras aldığı ana SingletonComponent yaradır.
@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ılmazdan əvvəl artıq enjeksiya edilib
}
}
@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 və View üçün annotasiyadır. Hər bir tip üçün Hilt komponenti yaradır: Activity-də @AndroidEntryPoint SingletonComponent-dən miras alan ActivityComponent yaradır. Uşaq komponent avtomatik olaraq valideynin bütün asılılıqlarını alır. @Inject lateinit var ilə field injection yalnız @AndroidEntryPoint ilə annotasiya olunmuş siniflərdə mövcuddur — adi siniflərdə constructor injection istifadə olunur.
@InstallIn modulun hansı Hilt komponentinə quraşdırıldığını göstərir. @InstallIn(SingletonComponent::class) ilə NetworkModule bütün tətbiqdə mövcuddur. @InstallIn(ActivityComponent::class) ilə Module — yalnız Activity-də. Bu, asılılıq qraflarını təcrid edir: Activity-ə xas modullar Fragment və ViewModel-də görünmür, icazəsiz asılılıqların təsadüfən istifadəsinin qarşısını alır. @ApplicationContext — tətbiq kontekstini əldə etmək üçün Hilt-in daxili kvalifikatorudur.
Eyni interfeysin iki fərqli reallaşdırmasını enjeksiya etmək tələb olunduqda, kvalifikatorlardan istifadə olunur. Hilt mətn identifikatorları üçün @Named-i və @Qualifier ilə fərdi annotasiyaları dəstəkləyir. Məsələn, müxtəlif mətn konfiqurasiyaları üçün @Named("baseUrl") və @Named("imageBaseUrl"). Fərdi kvalifikatorlar @Named-dən üstündür, çünki kompilasiya mərhələsində yoxlanılır — səhv mənim adı icra vaxtına qədər aşkarlanmaz.
@HiltViewModel — əl ilə ViewModelProvider.Factory fabrikini əvəz edən annotasiyadır. @HiltViewModel ilə annotasiya olunmuş və @Inject constructor-u olan sinif bütün asılılıqları avtomatik olaraq Dagger vasitəsilə alır. Hilt Jetpack ViewModelProvider tərəfindən istifadə olunan ViewModelFactory yaradır. Hilt olmadan proqramçı fabriki əl ilə yazmalı, hər parametri Activity və ya fragmentdən ötürməli olur.
@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-də — Hilt avtomatik ViewModel yaradır
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by viewModels()
}
ViewModelScoped — ViewModel yaşadıqca yaşayan asılılıqlar üçün Hilt scope-u. Eyni tipdə iki ViewModel eyni @ViewModelScoped asılılığını enjeksiya edərsə, hər biri öz nümunəsini alır. Bu, @ViewModelScoped-i @ActivityScoped-dən fərqləndirir, burada bir Activity bütün fraqmentlər üçün bir nümunə alır. ViewModel-ə xas asılılıqlar üçün (məsələn, SavedStateHandle) @HiltViewModel @Inject constructor(savedStateHandle: SavedStateHandle) ilə istifadə olunur.
Hilt Hilt Extensions kitabxanası vasitəsilə assisted injection-u dəstəkləyir. Assisted injection, asılılıqların bir hissəsi yalnız icra vaxtında məlum olduqda (məsələn, intent-dən istifadəçi ID-si) konstruktora parametrlərin ötürülməsinə imkan verir. Assisted injection üçün @AssistedInject @Assisted parametrləri ilə kombinasiyada istifadə olunur. Hilt standart şəkildə enjeksiya edilə bilən AssistedFactory yaradır.
Təmiz Dagger əl ilə Component yaradılmasını, scope'ların təyin edilməsini və hər bir Android komponentində enjeksiyanın konfiqurasiyasını tələb edir. Proqramçı AppComponent, ActivityComponent, FragmentComponent yaradır, onların əlaqələrini @Subcomponent vasitəsilə idarə edir. Bu yanaşma maksimal nəzarət verir, lakin əhəmiyyətli miqdarda boilerplate kodu tələb edir. Dagger qeyri-standart DI arxitekturası tələb olunan böyük layihələrdə və ya Android olmayan Java/Kotlin layihələrində istifadə olunur.
Hilt boilerplate-i avtomatlaşdırır: bir @HiltAndroidApp, hər komponent üçün bir @AndroidEntryPoint, əvvəlcədən təyin edilmiş scope'lar. Hilt Google tərəfindən bütün yeni Android layihələri üçün tövsiyə olunur. Dagger-dan Hilt-ə miqrasiya Component-in @InstallIn ilə əvəz edilməsini, @Subcomponent-in əvvəlcədən təyin edilmiş Hilt komponentləri ilə əvəz edilməsini və əl ilə ViewModelProvider.Factory-nin @HiltViewModel ilə əvəz edilməsini əhatə edir. Əksər @Module sinifləri @Provides metodlarını dəyişmədən @InstallIn əlavə edilməklə köçürülür.
| Xüsusiyyət | Dagger | Hilt |
|---|---|---|
| Konfiqurasiya | Əl ilə: Component, Subcomponent, Builder | Avtomatik: @HiltAndroidApp, @AndroidEntryPoint |
| Android komponentləri | Əvvəlcədən təyin edilmiş yoxdur | 12+ daxili komponent |
| ViewModel | Əl ilə fabrik | @HiltViewModel + @Inject constructor |
| Multimodul | @Component(dependencies) vasitəsilə | @InstallIn + aqreqasiya vasitəsilə |
| Mürəkkəblik | Yüksək — təcrübə tələb olunur | Aşağı — intuitiv |
| Çeviklik | Maksimal | Standart (95% ssenarini əhatə edir) |
Hilt məhdudiyyətləri: kitabxana yalnız Android-i dəstəkləyir (sırf server Java layihələri üçün uyğun deyil), müəyyən komponent strukturunu tətbiq edir (çətin dəyişdirilir) və Jetpack Compose layihələri üçün android.hilt:hilt-navigation-compose-dən asılılıq əlavə edir. Compose tətbiqləri üçün Hilt hiltViewModel() vasitəsilə Composable-da mövcud olan @HiltViewModel təqdim edir — Activity-dən ViewModel-i əl ilə təmin etmədən.
Tez-tez verilən suallar
Dagger — Component və Module-in əl ilə konfiqurasiyası ilə əsas kompilasiya vaxtı DI çərçivəsidir. Hilt — Android üçün əlavədir, komponentlərin yaradılmasını və Activity, Fragment, ViewModel, Service və BroadcastReceiver-in həyat dövrü ilə inteqrasiyanı avtomatlaşdırır.
@HiltAndroidApp Application üçün Hilt komponentinin yaradılmasını aktivləşdirir. Bu annotasiya olmadan Hilt bütün ActivityComponent, FragmentComponent və ViewModelComponent-in miras aldığı əsas SingletonComponent komponentini yarada bilməz. Annotasiya hər bir Hilt layihəsi üçün məcburidir.
Hilt Navigation NavBackStackEntry-də ViewModel üçün @HiltViewModel və naviqasiya qrafı çərçivəsində ViewModel-in scoplanması üçün hiltNavGraphViewModels() təqdim edir. android.hilt:hilt-navigation-fragment kitabxanası hər NavBackStackEntry üçün avtomatik ViewModel yaradır.
Tətbiq konteksti üçün @ApplicationContext və ya Activity konteksti üçün @ActivityContext istifadə edin. Hilt bu kvalifikatorları android.hilt:hilt-android kitabxanasında daxili olaraq təqdim edir. @ActivityContext yalnız ActivityComponent-də quraşdırılmış modullarda mövcuddur.
@Binds — metod dəqiq bir parametr qəbul etdikdə və onun tipini interfeys kimi qaytardıqda @Provides-ə effektiv alternativdir. @Binds metodu çağırmadan birbaşa cast yaradır, bu da yaradılan kodun miqdarını azaldır və enjeksiya zamanı performansı artırır.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun