Dagger / Hilt: apa itu, DI dan penerapan

Penulis: IT Sectr Diterbitkan: 2026-05-03 Waktu membaca: 9 mnt

Dagger — adalah framework injeksi ketergantungan untuk Java dan Kotlin yang menghasilkan kode DI pada tahap kompilasi melalui pemrosesan anotasi. Hilt — adalah lapisan di atas Dagger untuk Android yang menyederhanakan konfigurasi komponen dan siklus hidup. Menurut data Google, 2025, Hilt digunakan di lebih dari 70% aplikasi Android dari Google Play Top-100, mendukung Activity, Fragment, ViewModel dan Service melalui komponen yang telah ditentukan sebelumnya. Kedua framework menyediakan pemeriksaan grafik ketergantungan pada waktu kompilasi, menghilangkan kesalahan injeksi pada runtime.

Poin utama

  • Dagger — framework DI waktu kompilasi dengan pembuatan kode melalui anotasi @Module, @Provides, @Component
  • Hilt — lapisan Android yang menyederhanakan Dagger melalui @HiltAndroidApp, @AndroidEntryPoint, @HiltViewModel
  • Component — grafik ketergantungan yang menghubungkan Module dengan target Inject melalui metode proxy
  • Scope — @Singleton, @ViewModelScoped, @ActivityScoped mengelola masa hidup objek yang diinjeksi
  • Hilt mendukung proyek multi-modul melalui @InstallIn untuk grafik ketergantungan yang terisolasi

Apa itu Dagger / Hilt?

Dagger — adalah framework injeksi ketergantungan dengan pembuatan kode pada tahap kompilasi (compile-time DI). Dikembangkan di Square dan kemudian diserahkan ke Google, Dagger menggunakan pemroses anotasi Java APT untuk menganalisis grafik ketergantungan dan menghasilkan kelas pabrik. Berbeda dengan runtime-DI (Guice, Koin), Dagger tidak menggunakan refleksi — semua kode dibuat saat kompilasi, memberikan kinerja maksimal saat runtime dan deteksi kesalahan pada tahap build.

Hilt — adalah pustaka dari Google, dibangun di atas Dagger dan dioptimalkan untuk Android. Hilt menyediakan komponen yang telah ditentukan sebelumnya yang sesuai dengan siklus hidup komponen Android: @SingletonComponent untuk Application, @ActivityComponent untuk Activity, @FragmentComponent untuk Fragment, @ViewModelComponent untuk ViewModel. Ini menghilangkan konfigurasi rutin Component dan Module yang diperlukan di Dagger murni. Hilt juga menghasilkan grafik ketergantungan untuk setiap komponen Android secara otomatis melalui @AndroidEntryPoint.

Menurut Google I/O 2024, Hilt adalah solusi DI yang direkomendasikan untuk aplikasi Android yang ditulis di Kotlin. Pustaka Jetpack (Navigation, Room, WorkManager) memiliki integrasi bawaan dengan Hilt melalui @HiltViewModel dan @HiltWorker. Dalam proyek yang tidak menggunakan Android (pustaka Java/Kotlin murni, aplikasi server), Dagger murni diterapkan tanpa lapisan Hilt.

Masalah injeksi ketergantungan manual

Tanpa framework DI, pengembang membuat objek secara manual melalui konstruktor atau pabrik, meneruskan ketergantungan melalui rantai. Setiap kebutuhan baru — perubahan tanda tangan semua konstruktor dalam rantai. Dagger mengotomatiskan proses ini: cukup deklarasikan tipe apa yang diperlukan (@Inject constructor), dan Dagger akan membuat grafik ketergantungan, menyelesaikan semua tipe bersarang. Saat ketergantungan berubah, Dagger secara otomatis memperbarui kode yang dihasilkan — kesalahan dalam rantai tidak mungkin terjadi.

Prinsip injeksi ketergantungan

Injeksi ketergantungan (Dependency Injection) — adalah pola di mana objek menerima ketergantungannya dari luar, bukan membuatnya sendiri. DI mengimplementasikan prinsip inversi kontrol (IoC): kelas tidak bertanggung jawab untuk membuat ketergantungannya sendiri, melainkan mendeklarasikannya melalui konstruktor, metode, atau bidang. Injeksi melalui konstruktor (constructor injection) dianggap paling disukai karena menjamin objek dibuat dalam keadaan yang valid.

Tipe injeksiSintaks DaggerKapan digunakan
Constructor injection@Inject constructorCara utama — untuk semua kelas sendiri
Field injection@Inject lateinit varHanya untuk komponen Android (Activity, Fragment)
Method injection@Inject fun bind()Untuk inisialisasi post-construct

Keuntungan compile-time DI

Keuntungan utama DI meliputi kemampuan pengujian (ketergantungan dapat diganti dengan objek mock), keterikatan yang longgar (kelas bergantung pada antarmuka, bukan implementasi), dan manajemen siklus hidup objek yang eksplisit melalui scope. Dagger secara otomatis menjamin bahwa objek dibuat satu kali dalam scope-nya dan dihancurkan saat keluar dari scope.

Arsitektur Dagger: Component, Module, Provides

Component — elemen pusat grafik ketergantungan Dagger. Ini adalah antarmuka yang dianotasi dengan @Component yang menggambarkan jembatan antara Module dan target injeksi. Dagger menghasilkan implementasi Component (misalnya, DaggerAppComponent) pada tahap kompilasi. Component menentukan tipe mana yang tersedia untuk injeksi, melalui metode abstrak yang mengembalikan tipe yang diperlukan atau metode inject yang menerima objek untuk field injection.

kotlin
// Modul: menyediakan ketergantungan yang tidak dapat dibuat Dagger sendiri
@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)
    }
}

// Komponen: menghubungkan Module dan target injeksi
@Component(modules = [NetworkModule::class])
interface AppComponent {
    fun inject(activity: MainActivity)
    fun getApiService(): ApiService
}

@Module — adalah kelas yang berisi metode dengan @Provides yang mengembalikan instance ketergantungan. Module digunakan untuk tipe yang tidak dapat dibuat Dagger secara otomatis: pustaka pihak ketiga (OkHttp, Retrofit), objek dengan parameter konstruktor, antarmuka dengan pilihan implementasi. @Binds — alternatif untuk @Provides dalam kasus di mana metode mengembalikan antarmuka dan menerima satu implementasi: Dagger menghasilkan cast langsung tanpa memanggil metode.

@Scope menentukan masa hidup objek dalam grafik ketergantungan. @Singleton — objek dibuat satu kali untuk seluruh aplikasi. @ActivityScoped — objek hidup selama Activity hidup. @FragmentScoped — selama Fragment hidup. Tanpa scope, Dagger membuat instance baru setiap kali injeksi. @Reusable — scope untuk objek yang tidak harus singleton tetapi pembuatannya mahal — Dagger dapat menyimpan cache instance, tetapi tidak menjaminnya.

Hilt untuk Android: @HiltAndroidApp dan @AndroidEntryPoint

Hilt menyederhanakan konfigurasi Dagger untuk Android berkat komponen yang telah ditentukan sebelumnya dan pembuatan grafik dasar secara otomatis. Anotasi @HiltAndroidApp pada kelas Application memicu pembuatan komponen Hilt. Tanpa anotasi ini Hilt tidak berfungsi — wajib untuk setiap aplikasi Android yang menggunakan Hilt. @HiltAndroidApp membuat komponen induk SingletonComponent, yang diwarisi oleh semua komponen aplikasi lainnya.

kotlin
@HiltAndroidApp
class MyApplication : Application()

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject lateinit var apiService: ApiService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // apiService sudah diinjeksi sebelum pemanggilan onCreate
    }
}

@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 — anotasi untuk Activity, Fragment, Service, BroadcastReceiver dan View. Menghasilkan komponen Hilt untuk setiap tipe: @AndroidEntryPoint pada Activity membuat ActivityComponent yang mewarisi dari SingletonComponent. Komponen anak secara otomatis menerima semua ketergantungan induk. Field injection dengan @Inject lateinit var hanya tersedia di kelas yang dianotasi dengan @AndroidEntryPoint — di kelas biasa digunakan constructor injection.

@InstallIn menunjukkan di komponen Hilt mana modul dipasang. NetworkModule dengan @InstallIn(SingletonComponent::class) tersedia di seluruh aplikasi. Module dengan @InstallIn(ActivityComponent::class) — hanya di Activity. Ini mengisolasi grafik ketergantungan: modul khusus Activity tidak terlihat di Fragment dan ViewModel, mencegah penggunaan ketergantungan yang tidak diizinkan secara tidak sengaja. @ApplicationContext — kualifikasi bawaan Hilt untuk mendapatkan konteks aplikasi.

Qualifier: @Named dan kualifikasi kustom

Ketika diperlukan untuk menginjeksi dua implementasi berbeda dari antarmuka yang sama, kualifikasi digunakan. Hilt mendukung @Named untuk pengidentifikasi teks dan anotasi kustom dengan @Qualifier. Misalnya, @Named("baseUrl") dan @Named("imageBaseUrl") untuk konfigurasi teks yang berbeda. Kualifikasi kustom lebih diutamakan daripada @Named karena pemeriksaan pada tahap kompilasi — nama teks yang salah tidak akan terdeteksi hingga runtime.

Hilt ViewModel: @HiltViewModel dan @Inject constructor

@HiltViewModel — anotasi yang menggantikan pabrik manual ViewModelProvider.Factory. Kelas yang dianotasi dengan @HiltViewModel dengan @Inject constructor secara otomatis menerima semua ketergantungan melalui Dagger. Hilt menghasilkan ViewModelFactory yang digunakan oleh Jetpack ViewModelProvider. Tanpa Hilt, pengembang harus menulis pabrik secara manual, meneruskan setiap parameter dari Activity atau fragmen.

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()
        }
    }
}

// Di Activity — Hilt secara otomatis membuat ViewModel
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by viewModels()
}

ViewModelScoped — scope Hilt untuk ketergantungan yang hidup selama ViewModel hidup. Jika dua ViewModel dari tipe yang sama menginjeksi ketergantungan @ViewModelScoped yang sama, masing-masing mendapatkan instance-nya sendiri. Ini membedakan @ViewModelScoped dari @ActivityScoped, di mana satu Activity mendapatkan satu instance untuk semua fragmen. Untuk ketergantungan khusus ViewModel (misalnya, SavedStateHandle) gunakan @HiltViewModel dengan @Inject constructor(savedStateHandle: SavedStateHandle).

Hilt mendukung assisted injection melalui pustaka Hilt Extensions. Assisted injection memungkinkan penerusan parameter ke konstruktor selama injeksi, ketika sebagian ketergantungan hanya diketahui saat runtime (misalnya, ID pengguna dari intent). Untuk assisted injection gunakan @AssistedInject dalam kombinasi dengan parameter @Assisted. Hilt menghasilkan AssistedFactory yang dapat diinjeksi dengan cara standar.

Dagger vs Hilt: perbandingan dan migrasi

Dagger murni memerlukan pembuatan Component secara manual, pendefinisian scope, dan konfigurasi injeksi di setiap komponen Android. Pengembang membuat AppComponent, ActivityComponent, FragmentComponent, mengelola hubungan mereka melalui @Subcomponent. Pendekatan ini memberikan kontrol maksimal tetapi memerlukan sejumlah besar kode boilerplate. Dagger digunakan dalam proyek besar yang memerlukan arsitektur DI kustom atau dalam proyek non-Android Java/Kotlin.

Hilt mengotomatiskan boilerplate: satu @HiltAndroidApp, satu @AndroidEntryPoint untuk setiap komponen, scope yang telah ditentukan sebelumnya. Hilt direkomendasikan oleh Google untuk semua proyek Android baru. Migrasi dari Dagger ke Hilt meliputi penggantian Component dengan @InstallIn, penggantian @Subcomponent dengan komponen Hilt yang telah ditentukan, dan penggantian ViewModelProvider.Factory manual dengan @HiltViewModel. Sebagian besar kelas @Module dipindahkan dengan menambahkan @InstallIn tanpa mengubah metode @Provides.

KarakteristikDaggerHilt
KonfigurasiManual: Component, Subcomponent, BuilderOtomatis: @HiltAndroidApp, @AndroidEntryPoint
Komponen AndroidTidak ada yang ditentukan12+ komponen bawaan
ViewModelPabrik manual@HiltViewModel + @Inject constructor
Multi-modulMelalui @Component(dependencies)Melalui @InstallIn + agregasi
KompleksitasTinggi — memerlukan pengalamanRendah — intuitif
FleksibilitasMaksimalStandar (mencakup 95% skenario)

Keterbatasan Hilt: pustaka hanya mendukung Android (tidak cocok untuk proyek server Java murni), memaksakan struktur komponen tertentu (sulit ditimpa), dan menambahkan ketergantungan pada android.hilt:hilt-navigation-compose untuk proyek Jetpack Compose. Untuk aplikasi Compose, Hilt menyediakan @HiltViewModel yang tersedia di Composable melalui hiltViewModel() — tanpa menyediakan ViewModel secara manual dari Activity.

Pertanyaan yang sering diajukan

Apa perbedaan antara Dagger dan Hilt?

Dagger — framework DI dasar waktu kompilasi dengan konfigurasi manual Component dan Module. Hilt — lapisan Android yang mengotomatiskan pembuatan komponen dan integrasi dengan siklus hidup Activity, Fragment, ViewModel, Service dan BroadcastReceiver.

Untuk apa @HiltAndroidApp diperlukan?

@HiltAndroidApp mengaktifkan pembuatan komponen Hilt untuk Application. Tanpa anotasi ini Hilt tidak dapat membuat komponen dasar SingletonComponent, yang diwarisi oleh semua ActivityComponent, FragmentComponent dan ViewModelComponent. Anotasi ini wajib untuk setiap proyek Hilt.

Bagaimana Hilt bekerja dengan Jetpack Navigation?

Hilt Navigation menyediakan @HiltViewModel untuk ViewModel di NavBackStackEntry dan hiltNavGraphViewModels() untuk scoping ViewModel dalam grafik navigasi. Pustaka android.hilt:hilt-navigation-fragment secara otomatis membuat ViewModel untuk setiap NavBackStackEntry.

Bagaimana cara menginjeksi Context di Hilt?

Gunakan @ApplicationContext untuk konteks aplikasi atau @ActivityContext untuk konteks Activity. Hilt menyediakan kualifikasi ini bawaan di pustaka android.hilt:hilt-android. @ActivityContext hanya tersedia di modul yang dipasang di ActivityComponent.

Apa itu @Binds dan kapan digunakan?

@Binds — alternatif efisien untuk @Provides, ketika metode menerima tepat satu parameter dan mengembalikan tipenya sebagai antarmuka. @Binds menghasilkan cast langsung tanpa memanggil metode, yang mengurangi jumlah kode yang dihasilkan dan meningkatkan kinerja saat injeksi.

Ringkasan

  • Dagger — framework DI waktu kompilasi dengan anotasi @Module, @Provides, @Component dan pembuatan kode melalui APT
  • Hilt — lapisan Android di atas Dagger dengan @HiltAndroidApp, @AndroidEntryPoint, @InstallIn dan komponen yang telah ditentukan
  • Component mengelola grafik ketergantungan, Module menyediakan kelas pihak ketiga, Provides — pabrik objek
  • Scope (@Singleton, @ViewModelScoped, @ActivityScoped) menentukan masa hidup objek dalam grafik Dagger
  • @HiltViewModel mengotomatiskan pembuatan ViewModel, menghilangkan pabrik manual ViewModelProvider.Factory
  • @InstallIn mengisolasi modul berdasarkan komponen, mencegah kebocoran ketergantungan antar lapisan aplikasi
  • Hilt direkomendasikan oleh Google untuk semua proyek Android baru, Dagger — untuk non-Android dan arsitektur DI kustom

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga