Injeção de Dependência em Kotlin na Prática: 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: O que é Injeção de Dependência e por que você precisa dela em Kotlin?

Injeção de Dependência (DI) é um padrão de projeto que torna o código mais flexível, testável e sustentável. Em vez de um objeto criar suas próprias dependências, o DI as transmite (injeta) externamente. Em Kotlin, com sua sintaxe concisa e recursos poderosos, o DI se torna uma ferramenta especialmente elegante.

Imagine que você está escrevendo um aplicativo para pedir pizza. Você tem a classe OrderService, que precisa enviar notificações. Sem DI, ela ficaria assim:

class OrderService {    private val notifier = EmailNotifier() // Acoplamento rígido

fun placeOrder(order: Order) { // Lógica do pedido notifier.send("Seu pedido foi recebido!") }}

Problema: você não pode substituir facilmente EmailNotifier por SmsNotifier ou testar OrderService sem enviar e-mails reais. O DI resolve esse problema injetando a dependência através do construtor:

class OrderService(private val notifier: Notifier) {    fun placeOrder(order: Order) {        notifier.send("Seu pedido foi recebido!")    }}

Agora, OrderService não sabe como a notificação é enviada. Essa é a essência do DI: baixo acoplamento e alta reutilização.



Principais formas de implementar DI em Kotlin

Em Kotlin, existem três abordagens principais para injeção de dependências: DI manual, uso de bibliotecas (Koin, Dagger 2) e injeção através de frameworks (por exemplo, Spring). Vamos analisar cada uma na prática.



1. Injeção Manual de Dependências (Manual DI)

A maneira mais simples é passar dependências através de construtores ou setters. Isso não requer bibliotecas adicionais e é ideal para projetos pequenos.

Exemplo: Vamos criar um serviço simples para processar pagamentos.

// Interface do gateway de pagamentointerface PaymentGateway {    fun process(amount: Double): Boolean}

// Implementação via PayPalclass PayPalGateway : PaymentGateway { override fun process(amount: Double): Boolean { println("Processando pagamento $amount via PayPal") return true }}

// Serviço de pedidos com injeção de dependênciaclass OrderService(private val paymentGateway: PaymentGateway) { fun checkout(total: Double) { if (paymentGateway.process(total)) { println("Pedido realizado!") } }}

// Ponto de entrada — "fábrica" ou "container"fun main() { val gateway = PayPalGateway() val service = OrderService(gateway) service.checkout(100.0)}

Vantagens: Simplicidade, controle total, sem dependências de bibliotecas.
Desvantagens: À medida que o projeto cresce, o gerenciamento manual de todas as dependências se torna complexo (é necessário criar um "container" ou "fábrica" manualmente).



2. Injeção de Dependências com Koin

Koin é uma biblioteca leve para DI, escrita em Kotlin. Ela não usa reflexão e não requer geração de código, tornando-a ideal para projetos pequenos e médios.

Instalação: Adicione ao build.gradle.kts:

implementation("io.insert-koin:koin-core:3.5.6")

Exemplo de uso:

import org.koin.core.context.startKoinimport org.koin.dsl.module

// Módulo de dependênciasval appModule = module { single<PaymentGateway> { PayPalGateway() } factory { OrderService(get()) } // get() obtém automaticamente o PaymentGateway}

fun main() { startKoin { modules(appModule) }

// Obtém o serviço do container val service: OrderService = org.koin.core.component.get() service.checkout(200.0)}

Conceitos-chave do Koin:

  • single — cria uma única instância (singleton)

Blogs

Book Recommendations