Guia completo para injeção de dependência com Hilt no Android

  • O Hilt simplifica o Dagger ao fornecer contêineres automáticos alinhados com o ciclo de vida do Android.
  • Permite o desacoplamento de código por meio de injeção de construtor e módulos com @Provides e @Binds.
  • Gerencie o escopo das instâncias usando componentes específicos, como SingletonComponent ou ActivityComponent.
  • Isso facilita o desenvolvimento de arquiteturas escaláveis ​​e testáveis, especialmente em ambientes com Jetpack Compose e MVVM.

Hilt Android

Se você desenvolve aplicativos Android, provavelmente já se deparou com a necessidade de organizar melhor suas classes para evitar que o projeto se transforme em um caos completo. É aí que entra a injeção de dependência , um padrão de projeto que, embora possa parecer mágica à primeira vista, é essencialmente uma maneira de fornecer a cada classe os objetos de que ela precisa sem que a classe precise criá-los por conta própria.

O Hilt chega para nos resgatar da complexidade do Dagger, oferecendo uma camada superior que padroniza a inserção de dependências . Ao se integrar com o Jetpack, o Hilt gerencia automaticamente contêineres e ciclos de vida, permitindo que nos concentremos na lógica de negócios em vez de ficar movendo objetos como se estivéssemos em uma mudança de casa.

Configuração inicial do ambiente

Para começar a usar o Hilt, o primeiro passo é preparar o ambiente Gradle. É essencial adicionar o plugin `hilt-android-gradle-plugin` ao arquivo de configuração do seu projeto. Em seguida, no arquivo do módulo da sua aplicação, você precisa aplicar o plugin e adicionar as dependências correspondentes, garantindo que o compilador (seja kapt ou KSP) esteja configurado corretamente.

Um detalhe crucial é que, para que tudo funcione perfeitamente, o projeto deve ser configurado para usar o Java 17 (ou Java 8 para versões mais antigas), pois este é um pré-requisito para que o Hilt e o Jetpack Compose funcionem em conjunto sem problemas. Se você perceber que o programa não compila ao ativar o plugin, verifique se as versões do Kotlin e do KSP correspondem exatamente, já que mesmo uma pequena discrepância pode interromper todo o processo de compilação.

O Coração de Hilt: A Classe de Aplicação

Qualquer aplicativo que deseje se beneficiar desta biblioteca deve ter uma classe Application personalizada. Criá-la simplesmente não é suficiente; ela deve ser marcada com a anotação @HiltAndroidApp . Essa linha aciona a geração de código do Hilt e cria o contêiner raiz do aplicativo.

Contexto no Android
Artigo relacionado:
Guia completo sobre contexto no Android: o que é e como gerenciá-lo

Este componente de nível superior é vital porque se conecta ao ciclo de vida geral do aplicativo e serve como base para que todos os outros componentes acessem as dependências definidas neste nível. Claro, não se esqueça de registrar esta classe no arquivo AndroidManifest.xml usando o atributo `name`, ou o Hilt passará completamente despercebido.

Injetando dependências em componentes do Android

Assim que o aplicativo estiver pronto, podemos começar a injetar dependências em atividades, fragmentos, visualizações ou serviços. Para isso, usamos a anotação `@AndroidEntryPoint` . Isso informa ao Hilt que esta classe é um ponto de entrada e que ele deve gerar um componente específico para ela.

Quando queremos obter uma dependência específica dentro de uma Activity, usamos a injeção de dependência por meio da anotação `@Inject`. É muito importante lembrar que esses campos não podem ser privados ; se você tentar usar o modificador `private`, o compilador lançará um erro imediatamente. No caso do Jetpack Compose, basta anotar a Activity raiz para acessar os ViewModels diretamente dentro das funções composable.

Estratégias para definir vínculos

Hilt precisa saber como criar os objetos que solicitamos. A maneira mais direta é por meio da injeção de dependência no construtor , onde inserimos `@Inject` logo antes do construtor da classe. Isso permite que Hilt analise os parâmetros e determine como fornecer cada uma dessas dependências.

No entanto, existem casos em que não temos controle total sobre a classe, como ao usar bibliotecas externas como Retrofit ou OkHttpClient. É aí que entram os Módulos Hilt . Um módulo é uma classe anotada com @Module e deve incluir @InstallIn para especificar qual componente deve hospedar essa dependência.

  • Utilização de @Provides: Isso é usado quando a classe é de terceiros ou requer um padrão de construção complexo. Aqui, definimos uma função que retorna a instância necessária.
  • Usando @Binds: Essa é a opção ideal quando queremos vincular uma interface a uma implementação concreta. Ela é definida como uma função abstrata que diz ao Hilt: "quando alguém solicitar essa interface, forneça essa implementação."

Gestão do Escopo e do Ciclo de Vida

Por padrão, o Hilt cria uma nova instância sempre que uma dependência é solicitada. No entanto, às vezes precisamos que um objeto permaneça o mesmo durante toda a vida útil do aplicativo ou de uma tela. Para isso, usamos escopos de componentes.

Se marcarmos uma classe com @Singleton e a instalarmos no SingletonComponent, teremos uma única instância global. Se preferirmos que o objeto exista apenas durante a atividade, usamos @ActivityScoped dentro do ActivityComponent. É crucial não abusar dos escopos, pois manter objetos na memória por muito tempo pode afetar negativamente o desempenho da aplicação.

Casos Especiais e Qualificadores

Às vezes, precisamos injetar duas implementações diferentes da mesma interface. Para evitar sobrecarregar o compilador, usamos qualificadores . Um qualificador é essencialmente uma anotação personalizada usada para rotular uma associação específica, permitindo-nos diferenciar, por exemplo, entre um cliente HTTP para autenticação e um para solicitações gerais.

mvvm
Artigo relacionado:
MVVM: O padrão definitivo de arquitetura de software para aplicativos modernos

Além disso, o Hilt simplifica as coisas com qualificadores predefinidos como `@ApplicationContext` e `@ActivityContext`, permitindo-nos obter o contexto do Android sem precisar configurar módulos manualmente. Por fim, para classes que o Hilt não suporta nativamente (como `ContentProviders`), podemos usar a anotação `@EntryPoint` , criando uma ponte manual para extrair dependências do grafo do Hilt. Compartilhe esta informação para que mais usuários possam aprender sobre isso.


Adicionar como fonte preferencial no Google