Injecao de dependencias no Android: Hilt vs Koin - Guia completo e perguntas de entrevista 2026

Comparacao entre Hilt e Koin para injecao de dependencias no Android com exemplos de codigo, benchmarks de desempenho e perguntas de entrevista. Hilt 2.60, Koin 4.2.

Hilt vs Koin - Injecao de dependencias Android

A injecao de dependencias determina como as classes recebem suas dependencias em vez de cria-las diretamente. No ecossistema Android de 2026, dois frameworks dominam o cenario: Hilt (a solucao compile-time do Google construida sobre o Dagger) na versao 2.60.1, e Koin (um service locator leve que opera em tempo de execucao) na versao 4.2.2. A escolha entre ambos afeta tempos de compilacao, desempenho na inicializacao, testabilidade e a velocidade com que novos desenvolvedores sao integrados ao time.

DI em compile-time vs runtime

O Hilt valida todo o grafo de dependencias durante a compilacao e falha o build caso alguma vinculacao esteja ausente. O Koin resolve dependencias em tempo de execucao usando um DSL Kotlin, capturando erros de configuracao apenas quando o caminho de codigo afetado e executado. Essa diferenca fundamental determina todos os trade-offs entre os dois frameworks.

Como o Hilt funciona internamente

O Hilt gera componentes Dagger mapeados para classes do ciclo de vida do Android. A anotacao @HiltAndroidApp dispara a geracao de codigo em tempo de compilacao, produzindo factories e providers para cada vinculacao declarada. O KSP (Kotlin Symbol Processing) substituiu o KAPT como processador de anotacoes recomendado a partir do Hilt 2.48, reduzindo o tempo de processamento pela metade.

Uma configuracao tipica do Hilt envolve tres pecas: um modulo declarando as vinculacoes, um ponto de entrada (Activity, Fragment ou ViewModel) e a classe Application anotada com @HiltAndroidApp.

AppModule.ktkotlin
@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))
    }
}
UserViewModel.ktkotlin
@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()
        }
    }
}

O compilador verifica que UserRepository possui um provider valido antes mesmo da aplicacao ser executada. Vinculacoes ausentes se manifestam como erros de compilacao, nao como crashes em producao.

Configuracao do Koin e a abordagem DSL Kotlin

O Koin segue a direcao oposta: zero geracao de codigo, zero processamento de anotacoes. As dependencias sao declaradas em Kotlin puro usando um DSL, e o framework as resolve em tempo de execucao por meio de um registro global de servicos. O Koin 4.2 introduziu modulos lazy para carregamento paralelo na inicializacao e o motor CoreResolverV2 que otimiza a resolucao de escopos.

AppModule.ktkotlin
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()) }
}
MyApplication.ktkotlin
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidContext(this@MyApplication)
            modules(appModule)
        }
    }
}

O DSL e lido de forma natural e nao requer nenhum plugin de processamento de anotacoes na configuracao do Gradle. O custo: um erro de digitacao na resolucao get() so aparece em tempo de execucao quando o ponto de injecao afetado e acionado.

Benchmarks de desempenho: tempo de build vs custo em runtime

A questao do desempenho aparece em praticamente toda entrevista tecnica Android. Numeros concretos valem mais do que opinioes.

MetricaHilt 2.60 (KSP)Koin 4.2
Overhead build limpo+8-15s (geracao KSP)~0s (sem geracao)
Overhead build incremental+2-4s~0s
Inicializacao app (50 bindings)~0ms (codigo pre-gerado)~5-15ms (resolucao do grafo)
Inicializacao app (500 bindings)~0ms~30-80ms
Impacto no tamanho do APK+200-400 KB (codigo gerado)+100 KB (biblioteca runtime)
Deteccao de vinculacao ausenteErro de compilacaoCrash em runtime
SDK minimo requeridoAPI 23API 23

Para projetos com menos de 100 bindings, o overhead de runtime do Koin permanece imperceptivel. Acima de 300 bindings, o custo na inicializacao se torna mensuravel, embora os modulos lazy do Koin 4.2 mitiguem isso ao paralelizar o carregamento dos modulos.

Mudancas importantes no Hilt 2.60

O Dagger 2.60 removeu o suporte multidex e passou a exigir minSDK 23, alinhando-se aos requisitos do AndroidX. Projetos que visam API 21-22 nao podem mais usar o Hilt. Esta versao tambem requer AGP 9 e Gradle 9.1+ ao usar o plugin Gradle do Hilt.

Estrategias de teste com cada framework

A testabilidade e onde as diferencas arquiteturais se tornam praticas. O Hilt oferece @TestInstallIn para substituir modulos de producao por test doubles em tempo de compilacao. O Koin disponibiliza loadKoinModules() para sobreescrever definicoes em tempo de execucao.

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

Os testes com Hilt detectam modulos de teste mal configurados em tempo de compilacao. Os testes com Koin exigem gerenciamento cuidadoso do ciclo de vida (startKoin/stopKoin), mas oferecem mais flexibilidade para sobrecargas parciais de modulos.

Pronto para mandar bem nas entrevistas de Android?

Pratique com nossos simuladores interativos, flashcards e testes tecnicos.

Arquitetura multi-modulo: escalando DI entre features

Projetos Android de grande porte distribuem funcionalidades em modulos Gradle separados. O framework de DI precisa lidar com as fronteiras entre modulos de forma limpa. Ambos os frameworks se integram naturalmente com os padroes de modularizacao Android moderna.

Com o Hilt, cada modulo de feature declara seu proprio @Module anotado com @InstallIn. O Hilt mescla todos os modulos em uma hierarquia unica de componentes em tempo de compilacao. A arquitetura MVVM combina naturalmente com os componentes com escopo do Hilt.

feature-payments/PaymentModule.ktkotlin
@Module
@InstallIn(ViewModelComponent::class)
object PaymentModule {

    @Provides
    fun providePaymentGateway(
        retrofit: Retrofit // Provided by :app module
    ): PaymentGateway {
        return StripePaymentGateway(retrofit.create(PaymentApi::class.java))
    }
}

Com o Koin, os modulos de feature exportam suas declaracoes module {}, e o modulo da aplicacao carrega todos na inicializacao. Os modulos lazy do Koin 4.2 permitem carregamento adiado dos modulos de feature ate o primeiro acesso.

feature-payments/paymentModule.ktkotlin
val paymentModule = module {
    factory<PaymentGateway> {
        StripePaymentGateway(get<Retrofit>().create(PaymentApi::class.java))
    }
}

// app/MyApplication.kt — loads all feature modules
startKoin {
    modules(appModule, paymentModule, analyticsModule)
}

O Hilt impoe a visibilidade das dependencias por meio dos escopos de componentes. O Koin se baseia em convencoes: qualquer modulo pode acessar as definicoes de qualquer outro modulo, o que proporciona flexibilidade, mas pode gerar acoplamento implicito.

Consideracoes sobre Kotlin Multiplatform

O Koin suporta Kotlin Multiplatform (KMP) nativamente. O mesmo DSL module {} funciona no Android, iOS, Desktop e alvos Web. O Hilt e exclusivo do Android, pois depende de componentes de ciclo de vida especificos da plataforma e do processador de anotacoes do Dagger.

Para projetos que visam multiplas plataformas, o Koin e a unica opcao viavel entre os dois. Modulos de logica de negocio compartilhada podem declarar suas dependencias uma unica vez e injeta-las em todos os alvos.

Migracao entre frameworks

O Koin 4.2 introduziu um modulo ponte Dagger que permite uma migracao gradual. Times que estao migrando do Hilt para o Koin podem expor os modulos Dagger existentes atraves do service locator do Koin durante a transicao. Essa abordagem incremental evita uma reescrita completa, mas adiciona complexidade temporaria.

Perguntas frequentes de entrevista sobre DI no Android

Estas perguntas aparecem regularmente em entrevistas tecnicas Android. Cada resposta se mantem concisa e foca no que os entrevistadores esperam.

P: Qual e a diferenca entre injecao de dependencias em compile-time e runtime?

A injecao em compile-time (Hilt/Dagger) gera o codigo de injecao durante o build. O compilador valida todo o grafo de dependencias, capturando vinculacoes ausentes antes da execucao. A injecao em runtime (Koin) resolve dependencias quando sao solicitadas pela primeira vez, utilizando um padrao de registro de servicos. A injecao em compile-time produz uma inicializacao mais rapida, porem builds mais lentos; a injecao em runtime nao impacta o build, mas adia a deteccao de erros.

P: Quais escopos de componentes Hilt existem e como se mapeiam aos ciclos de vida do Android?

SingletonComponent persiste durante toda a vida da aplicacao. ActivityRetainedComponent sobrevive a mudancas de configuracao. ViewModelComponent tem escopo vinculado ao ciclo de vida de um ViewModel. ActivityComponent, FragmentComponent e ViewComponent seguem seus respectivos lifecycle owners do Android. Escopos personalizados podem estender essa hierarquia.

P: Como o Koin lida com a injecao de ViewModel no Jetpack Compose?

O Koin fornece koinViewModel() como funcao Composable que cria ou recupera um ViewModel com escopo no ViewModelStoreOwner mais proximo. Desde o Koin 4.2, koinNavViewModel() vincula o escopo dos ViewModels as entradas do grafo de navegacao ao usar a navegacao do Jetpack Compose. O Koin 4.2 tambem adicionou suporte nativo para o Jetpack Navigation 3.

P: Em quais situacoes o Koin seria uma escolha melhor do que o Hilt?

O Koin se encaixa melhor em projetos KMP (o Hilt e exclusivo do Android), aplicacoes de pequeno a medio porte onde o tempo de build importa mais que o tempo de inicializacao, e equipes que preferem um DSL Kotlin explicito em vez de configuracao baseada em anotacoes. Prototipos e provas de conceito tambem se beneficiam da configuracao minima do Koin.

Erro comum em entrevistas

Chamar o Koin de "framework de injecao de dependencias" e tecnicamente impreciso. O Koin e um service locator: as dependencias sao obtidas via get() em vez de injetadas via construtor. Entrevistadores familiarizados com essa distincao esperam que os candidatos a reconhecam. Hilt/Dagger realiza verdadeira injecao de dependencias por meio de chamadas a construtores geradas.

Framework de decisao: escolhendo entre Hilt e Koin

FatorHiltKoin
Validacao do grafoCompile-timeRuntime
Impacto no tempo de buildMaior (codegen KSP)Nenhum
Custo de inicializacaoQuase zeroEscala com o tamanho do grafo
Curva de aprendizadoMais ingreme (conceitos Dagger)Suave (DSL Kotlin puro)
Suporte KMPNaoSim
Integracao JetpackProfunda (Google oficial)Boa (comunidade + Navigation 3)
Escalabilidade do timeMais solida (escopos impostos)Flexivel (baseada em convencoes)
Testes@TestInstallIn (compile-safe)loadKoinModules (runtime)
SDK minimoAPI 23 (desde 2.60)API 23

Nenhum dos frameworks e universalmente superior. A escolha depende do tamanho do projeto, da experiencia do time e das plataformas-alvo.

Comece a praticar!

Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.

Fontes

Pontos-chave sobre Hilt vs Koin

  • O Hilt 2.60 com KSP entrega validacao do grafo em compile-time e custo de inicializacao quase zero, mas agora exige minSDK 23 e AGP 9+, posicionando-se como a escolha mais solida para grandes projetos Android de plataforma unica com requisitos rigorosos de confiabilidade
  • O Koin 4.2 com modulos lazy, CoreResolverV2 e a nova ponte Dagger reduz a diferenca de desempenho na inicializacao enquanto mantem zero impacto no build e compatibilidade completa com KMP
  • Ambos os frameworks lidam com arquiteturas multi-modulo, mas o Hilt impoe limites de escopo em compile-time enquanto o Koin depende de convencoes do time
  • Para a preparacao para entrevistas Android, entender o trade-off entre compile-time e runtime e saber articular quando cada framework se encaixa melhor e a base esperada
  • Migrar entre frameworks nao e trivial, mas a ponte Dagger do Koin agora oferece uma via incremental para times que estao abandonando o Hilt
Desafio do dia

Você saberia encontrar o bug em Android?

Um trecho real, um bug escondido, uma tentativa por dia. Sem conta para testar.

Anthony Fillion-Maillet

Escrito por

Anthony Fillion-Maillet

Fundador da SharpSkill

Desenvolvedor fullstack há mais de 10 anos. Dirige a SharpSkill e responde por tudo o que é publicado aqui.

Atualizado em 27 de setembro de 2026

Tags

#android
#hilt
#koin
#dependency-injection
#kotlin

Compartilhar

Artigos relacionados