Injeção de Dependência (Dependency Injection) em Kotlin: Guia Completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução à Injeção de Dependência em Kotlin



No desenvolvimento moderno com Kotlin, especialmente na criação de aplicativos Android, o princípio Dependency Injection (DI) tornou-se não apenas uma boa prática, mas uma necessidade. A injeção de dependências permite escrever código limpo, testável e escalável, reduzindo o acoplamento entre os componentes do sistema.



Neste artigo, vamos entender o que é Dependency Injection, quais problemas ele resolve e como implementar DI em Kotlin — desde a abordagem manual até o uso de frameworks populares como Hilt e Koin.



O que é Dependency Injection (Injeção de Dependência)?



Dependency Injection é um padrão de projeto no qual um objeto recebe suas dependências externamente, em vez de criá-las por conta própria. Em vez de escrever val engine = Engine() dentro da classe, nós "injetamos" uma instância pronta através do construtor, método ou campo.



Vamos considerar um exemplo simples sem DI:



class Car {    private val engine = Engine() // Acoplamento rígido

fun start() { engine.start() }}


Problema: a classe Car está rigidamente acoplada a uma implementação específica de Engine. É difícil de testar e estender.



Agora, um exemplo com DI via construtor:



class Car(private val engine: Engine) { // Dependência fornecida externamente

fun start() { engine.start() }}

// Usoval engine = Engine()val car = Car(engine)car.start()


Agora Car não sabe como Engine é criado. Podemos facilmente substituí-lo por um MockEngine para testes ou por outra implementação.



Por que DI é importante em Kotlin?



Kotlin, como uma linguagem moderna, oferece excelentes recursos para DI:



  • Null Safety — Kotlin ajuda a evitar NullPointerException ao trabalhar com dependências.
  • Sintaxe concisa — construtores com parâmetros tornam o DI natural.
  • Compatibilidade com Java — todos os frameworks DI populares (Dagger, Hilt) suportam Kotlin.
  • Estilo funcional — Kotlin permite usar lambdas e delegates para implementar DI.


Formas de implementar DI em Kotlin



1. Injeção Manual (Manual DI)



A maneira mais simples é passar dependências através do construtor. Para projetos pequenos, isso geralmente é suficiente.



class Database(private val connection: Connection)

class UserRepository(private val database: Database)

class UserViewModel(private val userRepository: UserRepository)

// Montagem manual de dependênciasfun main() { val connection = Connection("postgres://localhost:5432") val database = Database(connection) val repository = UserRepository(database) val viewModel = UserViewModel(repository)}


Desvantagem: à medida que o projeto cresce, o gerenciamento manual se torna complicado.



2. Service Locator (Antipadrão ou solução temporária)



Às vezes, usa-se o Service Locator — um objeto central que armazena todas as dependências. No entanto, isso é considerado um antipadrão, pois esconde as dependências reais da classe.



object ServiceLocator {    private val database = Database()    private val repository = UserRepository(database)        fun provideViewModel() = UserViewModel(repository)}

// Usoval viewModel = ServiceLocator.provideViewModel()


3. Frameworks DI: Hilt e Koin



Para projetos sérios, é melhor usar soluções prontas. Vamos considerar os dois mais populares para Kotlin/Android.



Hilt (baseado em Dagger)



Hilt é a biblioteca DI oficial do Google para Android. É baseada no Dagger, mas com uma API simplificada.



// 1. Anotação @HiltAndroidApp na Application@HiltAndroidAppclass MyApplication : Application(                

Blogs

Book Recommendations