Dependency Injection Android: Hilt vs Koin - Panduan Lengkap dan Pertanyaan Wawancara 2026
Perbandingan mendalam Hilt dan Koin untuk dependency injection Android dengan contoh kode praktis, benchmark performa, serta pertanyaan wawancara teknis. Diperbarui untuk Hilt 2.57 dan Koin 4.2.

Dependency injection merupakan pola desain yang menentukan bagaimana sebuah class memperoleh dependensinya tanpa harus membuat instance secara langsung. Di ekosistem Android pada tahun 2026, dua framework mendominasi: Hilt (solusi compile-time dari Google yang dibangun di atas Dagger) pada versi 2.57.1, dan Koin (service locator ringan berbasis runtime) pada versi 4.2.1. Pemilihan framework yang tepat berdampak pada waktu build, performa startup, kemudahan pengujian, serta kecepatan onboarding anggota tim baru.
Hilt memvalidasi seluruh dependency graph saat kompilasi dan menggagalkan build jika ada binding yang hilang. Koin menyelesaikan dependency saat runtime menggunakan Kotlin DSL, sehingga kesalahan konfigurasi baru terdeteksi ketika jalur kode terkait dieksekusi. Perbedaan fundamental inilah yang mendasari setiap trade-off antara kedua framework.
Cara Kerja Hilt di Balik Layar
Hilt menghasilkan komponen Dagger yang dipetakan ke class-class lifecycle Android. Anotasi @HiltAndroidApp memicu code generation saat kompilasi, menghasilkan factory dan provider untuk setiap binding yang dideklarasikan. KSP (Kotlin Symbol Processing) menggantikan KAPT sebagai annotation processor yang direkomendasikan sejak Hilt 2.48, memangkas waktu annotation processing hingga separuhnya.
Setup Hilt yang umum melibatkan tiga komponen: module yang mendeklarasikan binding, entry point (Activity, Fragment, atau ViewModel), dan class Application yang dianotasi dengan @HiltAndroidApp.
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideUserRepository(
retrofit: Retrofit
): UserRepository {
return UserRepositoryImpl(retrofit.create(UserApi::class.java))
}
}@HiltViewModel
class UserViewModel @Inject constructor(
private val userRepository: UserRepository
) : ViewModel() {
private val _users = MutableStateFlow<List<User>>(emptyList())
val users: StateFlow<List<User>> = _users.asStateFlow()
fun loadUsers() {
viewModelScope.launch {
_users.value = userRepository.getUsers()
}
}
}Compiler memverifikasi bahwa UserRepository memiliki provider yang valid sebelum aplikasi dijalankan. Binding yang hilang akan muncul sebagai build error, bukan runtime crash.
Setup Koin dan Pendekatan Kotlin DSL
Koin mengambil pendekatan sebaliknya: tanpa code generation, tanpa annotation processing. Dependency dideklarasikan dalam Kotlin murni menggunakan DSL, dan framework menyelesaikannya saat runtime melalui service registry global. Koin 4.2 memperkenalkan lazy modules untuk loading paralel saat startup dan engine CoreResolverV2 baru yang mengoptimalkan resolusi scope.
val appModule = module {
// Instance Retrofit singleton
single<Retrofit> {
Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
// Repository singleton yang di-bind ke interface
single<UserRepository> {
UserRepositoryImpl(get<Retrofit>().create(UserApi::class.java))
}
// ViewModel dengan repository yang di-inject
viewModel { UserViewModel(get()) }
}class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@MyApplication)
modules(appModule)
}
}
}DSL Koin terbaca secara alami dan tidak membutuhkan plugin annotation processing di konfigurasi Gradle. Konsekuensinya: kesalahan penulisan pada resolusi get() baru terdeteksi saat runtime ketika titik injeksi tersebut dieksekusi.
Benchmark Performa: Waktu Build vs Biaya Runtime
Pertanyaan tentang performa hampir selalu muncul di setiap wawancara Android. Angka konkret lebih berarti daripada sekadar opini.
| Metrik | Hilt 2.57 (KSP) | Koin 4.2 | |--------|-----------------|----------| | Overhead clean build | +8-15 detik (KSP code generation) | ~0 detik (tanpa code generation) | | Overhead incremental build | +2-4 detik | ~0 detik | | Startup aplikasi (50 binding) | ~0 md (kode pre-generated) | ~5-15 md (resolusi graph) | | Startup aplikasi (500 binding) | ~0 md | ~30-80 md | | Dampak ukuran APK | +200-400 KB (generated code) | +100 KB (runtime library) | | Deteksi binding hilang | Error kompilasi | Crash runtime |
Untuk proyek dengan kurang dari 100 binding, overhead runtime Koin tidak terasa. Di atas 300 binding, biaya startup mulai terukur, meskipun lazy modules di Koin 4.2 memitigasi hal ini dengan memparalelkan pemuatan module.
Beralih dari KAPT ke KSP untuk pemrosesan Hilt mengurangi waktu annotation processing sebesar 40-60%. Proyek manapun yang masih menggunakan KAPT dengan Hilt sebaiknya segera bermigrasi ke KSP. Hilt telah mendukung KSP sejak versi 2.48.
Strategi Pengujian pada Masing-Masing Framework
Kemudahan pengujian adalah area di mana perbedaan arsitektur benar-benar terasa. Hilt menyediakan @TestInstallIn untuk mengganti module produksi dengan test double saat kompilasi. Koin menawarkan loadKoinModules() untuk meng-override definisi saat runtime.
// Module test Hilt — menggantikan binding AppModule di tests
@Module
@TestInstallIn(
components = [SingletonComponent::class],
replaces = [AppModule::class]
)
object FakeAppModule {
@Provides
@Singleton
fun provideUserRepository(): UserRepository {
return FakeUserRepository() // Test double in-memory
}
}// Test Koin — override saat runtime
class UserViewModelTest : KoinTest {
@Before
fun setUp() {
startKoin {
modules(
module {
single<UserRepository> { FakeUserRepository() }
viewModel { UserViewModel(get()) }
}
)
}
}
@Test
fun `loads users from repository`() {
val viewModel: UserViewModel = get()
viewModel.loadUsers()
assertEquals(3, viewModel.users.value.size)
}
@After
fun tearDown() {
stopKoin()
}
}Test Hilt menangkap kesalahan konfigurasi test module saat kompilasi. Test Koin memerlukan pengelolaan lifecycle yang cermat (startKoin/stopKoin) tetapi menawarkan fleksibilitas lebih untuk partial module override.
Siap menguasai wawancara Android Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Arsitektur Multi-Module: Scaling DI Lintas Fitur
Proyek Android berskala besar membagi fitur ke dalam Gradle module. Framework DI harus mendukung batasan antar-module secara bersih.
Dengan Hilt, setiap feature module mendeklarasikan @Module sendiri yang dianotasi dengan @InstallIn. Hilt menggabungkan semua module menjadi hierarki komponen tunggal saat kompilasi. Arsitektur MVVM berpadu secara alami dengan scoped component milik Hilt.
@Module
@InstallIn(ViewModelComponent::class)
object PaymentModule {
@Provides
fun providePaymentGateway(
retrofit: Retrofit // Disediakan oleh module :app
): PaymentGateway {
return StripePaymentGateway(retrofit.create(PaymentApi::class.java))
}
}Dengan Koin, feature module mengekspor deklarasi module {} mereka, dan app module memuat semuanya saat startup. Lazy modules di Koin 4.2 memungkinkan pemuatan tertunda feature module hingga akses pertama.
val paymentModule = module {
factory<PaymentGateway> {
StripePaymentGateway(get<Retrofit>().create(PaymentApi::class.java))
}
}
// app/MyApplication.kt — memuat semua feature module
startKoin {
modules(appModule, paymentModule, analyticsModule)
}Hilt menegakkan visibilitas dependency melalui component scope. Koin mengandalkan konvensi — module manapun dapat mengakses definisi module lain, yang memberikan fleksibilitas tetapi dapat menimbulkan coupling implisit.
Pertimbangan Kotlin Multiplatform
Koin mendukung Kotlin Multiplatform (KMP) secara native. DSL module {} yang sama dapat digunakan di Android, iOS, Desktop, dan Web target. Hilt hanya untuk Android — framework ini bergantung pada komponen lifecycle khusus Android dan annotation processor Dagger.
Untuk proyek yang menargetkan beberapa platform, Koin merupakan satu-satunya pilihan yang layak di antara keduanya. Module business logic bersama dapat mendeklarasikan dependensinya sekali dan menginjeksinya ke semua target.
Pertanyaan Wawancara Umum tentang DI Android
Pertanyaan-pertanyaan berikut sering muncul dalam wawancara teknis Android. Setiap jawaban disajikan ringkas dan fokus pada hal-hal yang diharapkan pewawancara.
T: Apa perbedaan antara dependency injection compile-time dan runtime?
Compile-time DI (Hilt/Dagger) menghasilkan kode injeksi selama proses build. Compiler memvalidasi seluruh dependency graph, menangkap binding yang hilang sebelum runtime. Runtime DI (Koin) menyelesaikan dependency saat pertama kali diminta, menggunakan pola service registry. Compile-time DI menghasilkan startup lebih cepat tetapi build lebih lambat; runtime DI tidak membebani build sama sekali tetapi menunda deteksi error.
T: Scope komponen Hilt apa saja yang ada dan bagaimana pemetaannya ke lifecycle Android?
SingletonComponent hidup sepanjang siklus hidup aplikasi. ActivityRetainedComponent bertahan saat konfigurasi berubah. ViewModelComponent di-scope ke lifecycle ViewModel. ActivityComponent, FragmentComponent, dan ViewComponent mengikuti lifecycle owner Android masing-masing. Custom scope dapat memperluas hierarki ini.
T: Bagaimana Koin menangani injeksi ViewModel di Jetpack Compose?
Koin menyediakan koinViewModel() sebagai fungsi Composable yang membuat atau mengambil ViewModel yang di-scope ke ViewModelStoreOwner terdekat. Sejak Koin 4.2, koinNavViewModel() men-scope ViewModel ke entri navigation graph saat menggunakan navigasi Jetpack Compose.
T: Kapan Koin menjadi pilihan yang lebih baik dibanding Hilt?
Koin lebih cocok untuk proyek KMP (Hilt hanya Android), aplikasi berukuran kecil hingga menengah di mana waktu build lebih penting dari waktu startup, serta tim yang lebih menyukai DSL Kotlin eksplisit daripada konfigurasi berbasis anotasi. Proyek prototyping dan proof-of-concept juga mendapat manfaat dari setup Koin yang minimal.
Menyebut Koin sebagai "framework dependency injection" secara teknis kurang tepat. Koin merupakan service locator — dependency ditarik melalui get() alih-alih didorong melalui constructor injection. Pewawancara yang memahami perbedaan ini akan mengharapkan kandidat untuk mengakuinya. Hilt/Dagger melakukan true dependency injection melalui constructor call yang di-generate.
Kerangka Keputusan: Memilih Antara Hilt dan Koin
| Faktor | Hilt | Koin |
|--------|------|------|
| Validasi graph | Compile-time | Runtime |
| Dampak waktu build | Lebih tinggi (KSP codegen) | Tidak ada |
| Biaya startup | Mendekati nol | Skala sesuai ukuran graph |
| Kurva belajar | Lebih curam (konsep Dagger) | Landai (Kotlin DSL murni) |
| Dukungan KMP | Tidak | Ya |
| Integrasi Jetpack | Mendalam (resmi Google) | Baik (komunitas) |
| Skalabilitas tim | Lebih kuat (scope ditegakkan) | Fleksibel (berbasis konvensi) |
| Pengujian | @TestInstallIn (compile-safe) | loadKoinModules (runtime) |
Tidak ada framework yang unggul secara universal. Pilihan bergantung pada skala proyek, pengalaman tim, dan target platform.
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Kesimpulan
- Hilt 2.57 dengan KSP menawarkan validasi dependency graph saat kompilasi dan biaya startup mendekati nol, menjadikannya pilihan yang lebih kuat untuk proyek Android single-platform berskala besar dengan persyaratan reliabilitas ketat
- Koin 4.2 dengan lazy modules dan
CoreResolverV2menutup gap performa startup sambil mempertahankan nol overhead build dan kompatibilitas penuh dengan KMP - Kedua framework mendukung arsitektur multi-module, tetapi Hilt menegakkan batasan scope saat kompilasi sementara Koin mengandalkan konvensi tim
- Untuk persiapan wawancara Android, memahami trade-off antara compile-time vs runtime serta mampu mengartikulasikan kapan setiap framework cocok digunakan merupakan dasar yang diharapkan
- Migrasi antar framework bukan hal yang sepele — pilihan awal harus memperhitungkan lintasan platform dan skalabilitas jangka panjang proyek
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Tag
Bagikan
Artikel terkait

Kotlin 2.3 untuk Android: Name-Based Destructuring, KMP dan Pertanyaan Wawancara 2026
Pertanyaan wawancara Kotlin 2.3 untuk developer Android di tahun 2026. Name-based destructuring, KMP, context parameters, Flow, dan coroutines dengan contoh kode.

Jetpack Compose: Animasi Lanjutan Langkah demi Langkah
Panduan lengkap animasi lanjutan di Compose: transisi, AnimatedVisibility, Animatable, gestur, dan performa untuk antarmuka Android yang halus.

20 Pertanyaan Wawancara Jetpack Compose Teratas di Tahun 2026
20 pertanyaan wawancara Jetpack Compose yang paling sering ditanyakan: recomposition, state management, navigation, performa, dan pola arsitektur dengan contoh kode lengkap.