Dagger / Hilt: o que é, DI e aplicação

Autor: IT Sectr Publicado: 2026-05-03 Tempo de leitura: 9 min

Dagger é um framework de injeção de dependência para Java e Kotlin que gera código DI em tempo de compilação através do processamento de anotações. Hilt é uma camada sobre o Dagger para Android que simplifica a configuração de componentes e o gerenciamento do ciclo de vida. De acordo com Google, 2025, o Hilt é usado em mais de 70% dos aplicativos Android do Top-100 do Google Play, suportando Activity, Fragment, ViewModel e Service através de componentes predefinidos. Ambos os frameworks fornecem verificação do grafo de dependências em tempo de compilação, eliminando erros de injeção em tempo de execução.

Principais pontos

  • Dagger — framework DI em tempo de compilação com geração de código via anotações @Module, @Provides, @Component
  • Hilt — camada para Android que simplifica o Dagger através de @HiltAndroidApp, @AndroidEntryPoint, @HiltViewModel
  • Component — grafo de dependências conectando Module a alvos Inject através de métodos proxy
  • Scope — @Singleton, @ViewModelScoped, @ActivityScoped gerenciam o tempo de vida dos objetos injetados
  • Hilt suporta projetos multimódulo via @InstallIn para grafos de dependência isolados

O que é Dagger / Hilt?

Dagger é um framework de injeção de dependência com geração de código em tempo de compilação. Originalmente desenvolvido no Square e depois transferido para o Google, o Dagger usa o processador de anotações Java APT para analisar o grafo de dependências e gerar classes factory. Ao contrário de DI em tempo de execução (Guice, Koin), o Dagger não usa reflexão — todo o código é criado na compilação, garantindo máximo desempenho em tempo de execução e detecção de erros em tempo de build.

Hilt é uma biblioteca do Google construída sobre o Dagger e otimizada para Android. O Hilt fornece componentes predefinidos correspondentes ao ciclo de vida dos componentes Android: @SingletonComponent para Application, @ActivityComponent para Activity, @FragmentComponent para Fragment, @ViewModelComponent para ViewModel. Isso elimina a configuração rotineira de Component e Module necessária no Dagger puro. O Hilt também gera o grafo de dependências para cada componente Android automaticamente via @AndroidEntryPoint.

De acordo com o Google I/O 2024, o Hilt é a solução recomendada para DI em aplicativos Android escritos em Kotlin. As bibliotecas Jetpack (Navigation, Room, WorkManager) têm integração embutida com o Hilt via @HiltViewModel e @HiltWorker. Em projetos que não usam Android (bibliotecas Java/Kotlin puras, aplicações servidoras), usa-se o Dagger puro sem a camada do Hilt.

O problema da injeção manual de dependências

Sem um framework DI, o desenvolvedor cria objetos manualmente através de construtores ou fábricas, passando dependências ao longo da cadeia. Cada novo requisito significa alterar as assinaturas de todos os construtores na cadeia. Dagger automatiza esse processo: basta declarar qual tipo é necessário (@Inject constructor), e o Dagger cria o grafo de dependências, resolvendo todos os tipos aninhados. Quando as dependências mudam, o Dagger atualiza o código gerado automaticamente — é impossível errar na cadeia.

Princípios de injeção de dependência

Injeção de dependência é um padrão no qual um objeto recebe suas dependências de fora em vez de criá-las por si mesmo. DI implementa o princípio de Inversão de Controle (IoC): uma classe não é responsável por criar suas próprias dependências, mas as declara através de um construtor, método ou campo. A injeção por construtor é considerada a mais preferível porque garante que o objeto seja criado em um estado válido.

Tipo de injeçãoSintaxe do DaggerQuando usar
Constructor injection@Inject constructorMétodo principal — para todas as classes próprias
Field injection@Inject lateinit varApenas para componentes Android (Activity, Fragment)
Method injection@Inject fun bind()Para inicialização pós-construção

Vantagens do DI em tempo de compilação

As principais vantagens do DI incluem testabilidade (as dependências podem ser substituídas por objetos mock), baixo acoplamento (classes dependem de interfaces, não de implementações) e gerenciamento explícito do ciclo de vida de objetos através de scopes. Dagger garante automaticamente que um objeto seja criado uma vez dentro de seu escopo e destruído ao sair do escopo.

Arquitetura do Dagger: Component, Module, Provides

Component é o elemento central do grafo de dependências do Dagger. É uma interface anotada com @Component que descreve a ponte entre Module e os alvos de injeção. O Dagger gera a implementação do Component (por exemplo, DaggerAppComponent) em tempo de compilação. O Component determina quais tipos estão disponíveis para injeção através de métodos abstratos que retornam os tipos necessários ou através de métodos inject que aceitam um objeto para field injection.

kotlin
// Module: fornece dependências que o Dagger não pode criar sozinho
@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)
    }
}

// Component: conecta Module e alvos de Injection
@Component(modules = [NetworkModule::class])
interface AppComponent {
    fun inject(activity: MainActivity)
    fun getApiService(): ApiService
}

@Module é uma classe contendo métodos com @Provides que retornam instâncias de dependências. Module é usado para tipos que o Dagger não pode criar automaticamente: bibliotecas de terceiros (OkHttp, Retrofit), objetos com parâmetros de construtor, interfaces com seleção de implementação. @Binds é uma alternativa ao @Provides para casos em que um método retorna uma interface e aceita uma única implementação: o Dagger gera um cast direto sem chamar o método.

@Scope define o tempo de vida de um objeto no grafo de dependências. @Singleton — o objeto é criado uma vez para toda a aplicação. @ActivityScoped — o objeto vive enquanto a Activity viver. @FragmentScoped — enquanto o Fragment viver. Sem escopo, o Dagger cria uma nova instância a cada injeção. @Reusable — um escopo para objetos que não precisam ser singletons mas cuja criação é cara — o Dagger pode armazenar a instância em cache mas não garante isso.

Hilt para Android: @HiltAndroidApp e @AndroidEntryPoint

Hilt simplifica a configuração do Dagger para Android através de componentes predefinidos e geração automática do grafo base. A anotação @HiltAndroidApp na classe Application aciona a geração do componente Hilt. Sem esta anotação, o Hilt não funciona — é obrigatória para qualquer aplicativo Android que use Hilt. @HiltAndroidApp cria o componente pai SingletonComponent, do qual todos os outros componentes da aplicação herdam.

kotlin
@HiltAndroidApp
class MyApplication : Application()

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject lateinit var apiService: ApiService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // apiService já injetado antes da chamada 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 é uma anotação para Activity, Fragment, Service, BroadcastReceiver e View. Ela gera um componente Hilt para cada tipo: @AndroidEntryPoint em uma Activity cria um ActivityComponent que herda de SingletonComponent. O componente filho recebe automaticamente todas as dependências do pai. Field injection com @Inject lateinit var está disponível apenas em classes anotadas com @AndroidEntryPoint — em classes normais, usa-se constructor injection.

@InstallIn especifica em qual componente Hilt um módulo é instalado. NetworkModule com @InstallIn(SingletonComponent::class) está disponível em toda a aplicação. Um Module com @InstallIn(ActivityComponent::class) está disponível apenas na Activity. Isso isola os grafos de dependência: módulos específicos de Activity não são visíveis em Fragment e ViewModel, prevenindo o uso acidental de dependências inválidas. @ApplicationContext é um qualificador embutido do Hilt para obter o Context da aplicação.

Qualifier: @Named e qualificadores personalizados

Quando duas implementações diferentes da mesma interface precisam ser injetadas, usam-se qualificadores. O Hilt suporta @Named para identificadores de string e anotações personalizadas com @Qualifier. Por exemplo, @Named("baseUrl") e @Named("imageBaseUrl") para diferentes configurações de string. Qualificadores personalizados são preferíveis ao @Named devido à verificação em tempo de compilação — um nome de string incorreto não será detectado até o tempo de execução.

Hilt ViewModel: @HiltViewModel e @Inject constructor

@HiltViewModel é uma anotação que substitui a fábrica manual ViewModelProvider.Factory. Uma classe anotada com @HiltViewModel com @Inject constructor recebe automaticamente todas as dependências através do Dagger. O Hilt gera uma ViewModelFactory usada pelo Jetpack ViewModelProvider. Sem o Hilt, o desenvolvedor precisa escrever a fábrica manualmente, passando cada parâmetro da Activity ou fragmento.

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

// Na Activity — Hilt cria automaticamente o ViewModel
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by viewModels()
}

ViewModelScoped é um escopo do Hilt para dependências que vivem enquanto o ViewModel viver. Se dois ViewModels do mesmo tipo injetam a mesma dependência @ViewModelScoped, cada um recebe sua própria instância. Isso distingue @ViewModelScoped de @ActivityScoped, onde uma Activity recebe uma instância para todos os fragmentos. Para dependências específicas de ViewModel (por exemplo, SavedStateHandle), usa-se @HiltViewModel com @Inject constructor(savedStateHandle: SavedStateHandle).

O Hilt suporta assisted injection através da biblioteca Hilt Extensions. A injeção assistida permite passar parâmetros ao construtor no momento da injeção quando algumas dependências só são conhecidas em tempo de execução (por exemplo, o ID do usuário de uma intent). Para assisted injection, usa-se @AssistedInject em combinação com parâmetros @Assisted. O Hilt gera uma AssistedFactory que pode ser injetada da forma padrão.

Dagger vs Hilt: comparação e migração

Dagger puro requer a criação manual de Component, definição de escopos e configuração da injeção em cada componente Android. O desenvolvedor cria AppComponent, ActivityComponent, FragmentComponent e gerencia seus relacionamentos através de @Subcomponent. Esta abordagem dá máximo controle mas requer uma quantidade significativa de código boilerplate. O Dagger é usado em projetos grandes que exigem uma arquitetura DI não padrão, ou em projetos Java/Kotlin não Android.

Hilt automatiza o boilerplate: um @HiltAndroidApp, um @AndroidEntryPoint para cada componente, escopos predefinidos. O Google recomenda o Hilt para todos os novos projetos Android. A migração do Dagger para o Hilt inclui substituir Component por @InstallIn, substituir @Subcomponent por componentes Hilt predefinidos e substituir a fábrica manual ViewModelProvider.Factory por @HiltViewModel. A maioria das classes @Module é migrada com a adição de @InstallIn sem alterar os métodos @Provides.

CaracterísticaDaggerHilt
ConfiguraçãoManual: Component, Subcomponent, BuilderAutomática: @HiltAndroidApp, @AndroidEntryPoint
Componentes AndroidSem predefinição12+ componentes integrados
ViewModelFábrica manual@HiltViewModel + @Inject constructor
MultimóduloVia @Component(dependencies)Via @InstallIn + agregação
ComplexidadeAlta — experiência necessáriaBaixa — intuitivamente compreensível
FlexibilidadeMáximaPadrão (cobre 95% dos cenários)

Limitações do Hilt: a biblioteca só suporta Android (não adequada para projetos Java puramente servidores), impõe uma certa estrutura de componentes (difícil de sobrescrever) e adiciona uma dependência ao android.hilt:hilt-navigation-compose para projetos Jetpack Compose. Para aplicações Compose, o Hilt fornece @HiltViewModel acessível em Composable através de hiltViewModel() — sem necessidade de fornecer ViewModel manualmente a partir da Activity.

Perguntas frequentes

Qual é a diferença entre Dagger e Hilt?

Dagger é um framework DI básico em tempo de compilação com configuração manual de Component e Module. Hilt é uma camada para Android que automatiza a criação de componentes e a integração com o ciclo de vida de Activity, Fragment, ViewModel, Service e BroadcastReceiver.

Por que o @HiltAndroidApp é necessário?

@HiltAndroidApp ativa a geração do componente Hilt para Application. Sem esta anotação, o Hilt não pode criar o SingletonComponent base do qual todos os ActivityComponent, FragmentComponent e ViewModelComponent herdam. A anotação é obrigatória para qualquer projeto Hilt.

Como o Hilt funciona com Jetpack Navigation?

Hilt Navigation fornece @HiltViewModel para ViewModel em NavBackStackEntry e hiltNavGraphViewModels() para escopar ViewModel dentro do grafo de navegação. A biblioteca android.hilt:hilt-navigation-fragment cria automaticamente um ViewModel para cada NavBackStackEntry.

Como injetar Context no Hilt?

Use @ApplicationContext para o contexto da aplicação ou @ActivityContext para o contexto da Activity. O Hilt fornece esses qualificadores embutidos na biblioteca android.hilt:hilt-android. @ActivityContext está disponível apenas em módulos instalados no ActivityComponent.

O que é @Binds e quando usá-lo?

@Binds é uma alternativa eficiente ao @Provides quando um método aceita exatamente um parâmetro e retorna seu tipo como interface. @Binds gera um cast direto sem chamar o método, reduzindo a quantidade de código gerado e melhorando o desempenho da injeção.

Resumo

  • Dagger — framework DI em tempo de compilação com anotações @Module, @Provides, @Component e geração de código via APT
  • Hilt — camada Android sobre o Dagger com @HiltAndroidApp, @AndroidEntryPoint, @InstallIn e componentes predefinidos
  • Component gerencia o grafo de dependências, Module fornece classes de terceiros, Provides fornece fábricas de objetos
  • Scope (@Singleton, @ViewModelScoped, @ActivityScoped) define o tempo de vida do objeto no grafo do Dagger
  • @HiltViewModel automatiza a criação de ViewModel, eliminando as fábricas manuais ViewModelProvider.Factory
  • @InstallIn isola módulos por componentes, prevenindo vazamento de dependências entre camadas da aplicação
  • Hilt é recomendado pelo Google para todos os novos projetos Android, Dagger para arquiteturas DI não Android e personalizadas

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também