Inyeccion de dependencias en Android: Hilt vs Koin - Guia completa y preguntas de entrevista 2026
Comparacion detallada entre Hilt y Koin para inyeccion de dependencias en Android: ejemplos de codigo, benchmarks de rendimiento y preguntas frecuentes de entrevistas tecnicas en 2026.

La inyeccion de dependencias define como las clases obtienen sus dependencias en lugar de crearlas directamente. En el ecosistema Android de 2026, dos frameworks dominan el panorama: Hilt (la solucion compile-time de Google basada en Dagger) en su version 2.57.1, y Koin (un service locator ligero que opera en tiempo de ejecucion) en su version 4.2.1. La eleccion entre ambos impacta los tiempos de compilacion, el rendimiento al inicio, la testabilidad y la velocidad con que un equipo incorpora nuevos desarrolladores.
Hilt valida el grafo completo de dependencias durante la compilacion y hace fallar el build si falta alguna vinculacion. Koin resuelve las dependencias en tiempo de ejecucion mediante un DSL de Kotlin, detectando errores de configuracion solo cuando se ejecuta la ruta de codigo afectada. Esta diferencia fundamental determina cada compromiso entre ambos frameworks.
Como funciona Hilt internamente
Hilt genera componentes Dagger mapeados a las clases del ciclo de vida de Android. La anotacion @HiltAndroidApp activa la generacion de codigo en tiempo de compilacion, produciendo factories y providers para cada vinculacion declarada. KSP (Kotlin Symbol Processing) reemplazo a KAPT como procesador de anotaciones recomendado a partir de Hilt 2.48, reduciendo el tiempo de procesamiento aproximadamente a la mitad.
Una configuracion tipica de Hilt involucra tres piezas: un modulo que declara las vinculaciones, un punto de entrada (Activity, Fragment o ViewModel) y la clase Application anotada con @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()
}
}
}El compilador verifica que UserRepository tenga un provider valido antes de que la aplicacion se ejecute. Las vinculaciones faltantes aparecen como errores de compilacion, no como crashes en produccion.
Configuracion de Koin y el enfoque DSL de Kotlin
Koin toma el camino opuesto: cero generacion de codigo, cero procesamiento de anotaciones. Las dependencias se declaran en Kotlin puro usando un DSL, y el framework las resuelve en tiempo de ejecucion a traves de un registro global de servicios. Koin 4.2 introdujo los modulos lazy para carga paralela al inicio y un nuevo motor CoreResolverV2 que optimiza la resolucion de scopes.
val appModule = module {
// Singleton Retrofit instance
single<Retrofit> {
Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
// Singleton repository bound to its interface
single<UserRepository> {
UserRepositoryImpl(get<Retrofit>().create(UserApi::class.java))
}
// ViewModel with injected repository
viewModel { UserViewModel(get()) }
}class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@MyApplication)
modules(appModule)
}
}
}El DSL se lee de forma natural y no requiere ningun plugin de procesamiento de anotaciones en la configuracion de Gradle. La contrapartida: un error tipografico en la resolucion get() solo aparece en tiempo de ejecucion cuando se ejecuta el punto de inyeccion afectado.
Benchmarks de rendimiento: tiempo de build vs costo en runtime
La pregunta sobre rendimiento surge en practicamente toda entrevista tecnica Android. Los numeros concretos importan mas que las opiniones.
| Metrica | Hilt 2.57 (KSP) | Koin 4.2 | |---------|-----------------|----------| | Sobrecarga build limpio | +8-15s (generacion KSP) | ~0s (sin generacion) | | Sobrecarga build incremental | +2-4s | ~0s | | Inicio app (50 bindings) | ~0ms (codigo pre-generado) | ~5-15ms (resolucion del grafo) | | Inicio app (500 bindings) | ~0ms | ~30-80ms | | Impacto tamano APK | +200-400 KB (codigo generado) | +100 KB (libreria runtime) | | Deteccion vinculacion faltante | Error de compilacion | Crash en runtime |
Para proyectos con menos de 100 bindings, la sobrecarga runtime de Koin permanece imperceptible. Mas alla de 300 bindings, el costo de inicio se vuelve medible, aunque los modulos lazy de Koin 4.2 mitigan este problema al paralelizar la carga de modulos.
Migrar de KAPT a KSP para el procesamiento de Hilt reduce el tiempo de procesamiento de anotaciones entre un 40 y un 60 %. Cualquier proyecto que todavia utilice KAPT con Hilt deberia migrar a KSP de inmediato. Hilt soporta KSP desde la version 2.48.
Estrategias de testing con cada framework
La testabilidad es el area donde las diferencias arquitectonicas se vuelven practicas. Hilt provee @TestInstallIn para reemplazar modulos de produccion con dobles de prueba en tiempo de compilacion. Koin ofrece loadKoinModules() para sobreescribir definiciones en tiempo de ejecucion.
// Hilt test module — replaces AppModule bindings in tests
@Module
@TestInstallIn(
components = [SingletonComponent::class],
replaces = [AppModule::class]
)
object FakeAppModule {
@Provides
@Singleton
fun provideUserRepository(): UserRepository {
return FakeUserRepository() // In-memory test double
}
}// Koin test — override at 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()
}
}Las pruebas con Hilt detectan modulos de test mal configurados en tiempo de compilacion. Las pruebas con Koin requieren una gestion cuidadosa del ciclo de vida (startKoin/stopKoin) pero ofrecen mayor flexibilidad para sobrecargas parciales de modulos.
¿Listo para aprobar tus entrevistas de Android?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Arquitectura multi-modulo: escalando DI entre features
Los proyectos Android de gran escala distribuyen las funcionalidades en modulos Gradle separados. El framework de DI debe manejar los limites entre modulos de forma limpia.
Con Hilt, cada modulo de feature declara su propio @Module anotado con @InstallIn. Hilt fusiona todos los modulos en una jerarquia unica de componentes en tiempo de compilacion. La arquitectura MVVM se combina naturalmente con los componentes con scope de Hilt.
@Module
@InstallIn(ViewModelComponent::class)
object PaymentModule {
@Provides
fun providePaymentGateway(
retrofit: Retrofit // Provided by :app module
): PaymentGateway {
return StripePaymentGateway(retrofit.create(PaymentApi::class.java))
}
}Con Koin, los modulos de feature exportan sus declaraciones module {}, y el modulo de la aplicacion los carga todos al inicio. Los modulos lazy de Koin 4.2 permiten la carga diferida de modulos de features hasta el primer acceso.
val paymentModule = module {
factory<PaymentGateway> {
StripePaymentGateway(get<Retrofit>().create(PaymentApi::class.java))
}
}
// app/MyApplication.kt — loads all feature modules
startKoin {
modules(appModule, paymentModule, analyticsModule)
}Hilt impone la visibilidad de las dependencias mediante scopes de componentes. Koin se basa en convenciones: cualquier modulo puede acceder a las definiciones de cualquier otro modulo, lo que brinda flexibilidad pero puede generar acoplamiento implicito.
Consideraciones para Kotlin Multiplatform
Koin soporta Kotlin Multiplatform (KMP) de forma nativa. El mismo DSL module {} funciona en Android, iOS, Desktop y targets Web. Hilt es exclusivo de Android, ya que depende de componentes de ciclo de vida especificos de la plataforma y del procesador de anotaciones de Dagger.
Para proyectos que apuntan a multiples plataformas, Koin es la unica opcion viable entre ambos. Los modulos de logica de negocio compartida pueden declarar sus dependencias una sola vez e inyectarlas en todos los targets.
Preguntas frecuentes de entrevista sobre DI en Android
Estas preguntas aparecen de manera recurrente en las entrevistas tecnicas de Android. Cada respuesta se mantiene concisa y se enfoca en lo que los entrevistadores esperan.
P: Cual es la diferencia entre inyeccion de dependencias en compile-time y en runtime?
La inyeccion en compile-time (Hilt/Dagger) genera el codigo de inyeccion durante el build. El compilador valida el grafo completo de dependencias, detectando vinculaciones faltantes antes del runtime. La inyeccion en runtime (Koin) resuelve las dependencias cuando se solicitan por primera vez, utilizando un patron de registro de servicios. La inyeccion en compile-time produce un inicio mas rapido pero builds mas lentos; la inyeccion en runtime no tiene impacto en el build pero difiere la deteccion de errores.
P: Que scopes de componentes Hilt existen y como se mapean a los ciclos de vida de Android?
SingletonComponent vive durante toda la aplicacion. ActivityRetainedComponent sobrevive a los cambios de configuracion. ViewModelComponent tiene scope al ciclo de vida de un ViewModel. ActivityComponent, FragmentComponent y ViewComponent siguen a sus respectivos lifecycle owners de Android. Se pueden crear scopes personalizados para extender esta jerarquia.
P: Como maneja Koin la inyeccion de ViewModel en Jetpack Compose?
Koin proporciona koinViewModel() como funcion Composable que crea o recupera un ViewModel con scope al ViewModelStoreOwner mas cercano. Desde Koin 4.2, koinNavViewModel() asigna scope a los ViewModels segun las entradas del grafo de navegacion al utilizar Jetpack Compose navigation.
P: En que casos Koin seria mejor opcion que Hilt?
Koin se adapta mejor a proyectos KMP (Hilt es solo Android), aplicaciones de tamano pequeno a mediano donde el tiempo de build importa mas que el tiempo de inicio, y equipos que prefieren un DSL de Kotlin explicito sobre la configuracion basada en anotaciones. Los prototipos y pruebas de concepto tambien se benefician de la configuracion minima de Koin.
Llamar a Koin un "framework de inyeccion de dependencias" es tecnicamente impreciso. Koin es un service locator: las dependencias se obtienen mediante get() en lugar de inyectarse via constructor. Los entrevistadores familiarizados con esta distincion esperan que los candidatos la reconozcan. Hilt/Dagger realiza verdadera inyeccion de dependencias a traves de llamadas a constructores generadas.
Marco de decision: elegir entre Hilt y Koin
| Factor | Hilt | Koin |
|--------|------|------|
| Validacion del grafo | Compile-time | Runtime |
| Impacto en tiempo de build | Mayor (codegen KSP) | Ninguno |
| Costo de inicio | Casi cero | Escala con el tamano del grafo |
| Curva de aprendizaje | Mas pronunciada (conceptos Dagger) | Suave (DSL Kotlin puro) |
| Soporte KMP | No | Si |
| Integracion Jetpack | Profunda (Google oficial) | Buena (comunidad) |
| Escalabilidad de equipo | Mas solida (scopes impuestos) | Flexible (basada en convenciones) |
| Testing | @TestInstallIn (compile-safe) | loadKoinModules (runtime) |
Ningun framework es universalmente superior. La eleccion depende del tamano del proyecto, la experiencia del equipo y las plataformas objetivo.
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Conclusion
- Hilt 2.57 con KSP ofrece validacion del grafo en compile-time y un costo de inicio casi nulo, posicionandose como la opcion mas robusta para proyectos Android grandes de una sola plataforma con requisitos estrictos de confiabilidad
- Koin 4.2 con modulos lazy y
CoreResolverV2reduce la brecha de rendimiento al inicio mientras mantiene cero impacto en el build y compatibilidad completa con KMP - Ambos frameworks manejan arquitecturas multi-modulo, pero Hilt impone los limites de scope en compile-time mientras Koin depende de las convenciones del equipo
- Para la preparacion de entrevistas Android, comprender el compromiso compile-time vs runtime y saber articular cuando cada framework es la mejor opcion constituye la base esperada
- Migrar entre frameworks no es trivial: la eleccion inicial debe considerar la trayectoria del proyecto a largo plazo en terminos de plataformas y escalabilidad
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Etiquetas
Compartir
Artículos relacionados

Kotlin 2.3 para Android: Desestructuración por Nombre, KMP y Preguntas de Entrevista 2026
Preguntas de entrevista sobre Kotlin 2.3 para desarrolladores Android en 2026. Desestructuración por nombre, KMP, parámetros de contexto, Flow y coroutines con ejemplos de código.

Jetpack Compose: Animaciones Avanzadas Paso a Paso
Guía completa de animaciones avanzadas en Compose: transiciones, AnimatedVisibility, Animatable, gestos y rendimiento para interfaces Android fluidas.

Las 20 preguntas más frecuentes de Jetpack Compose en entrevistas (2026)
Las 20 preguntas de entrevista sobre Jetpack Compose más comunes: recomposición, gestión de estado, navegación, rendimiento y patrones de arquitectura.