Koin — Contêiner de Injeção de Dependência para Kotlin
No desenvolvimento moderno com Kotlin, o gerenciamento de dependências é uma tarefa importante. Koin é um contêiner leve de Injeção de Dependência (DI) escrito em Kotlin, que não requer geração de código, reflexão ou configuração complexa. Ao contrário do Dagger ou Spring, o Koin usa uma DSL simples e se integra totalmente com corrotinas e Flow. Nesta página, vamos abordar como instalar o Koin, declarar módulos, injetar dependências e usá-lo em projetos educacionais.
O que é Injeção de Dependência?
Injeção de Dependência (DI) é um padrão no qual um objeto recebe suas dependências de fora, em vez de criá-las por si só. Isso simplifica os testes, torna o código mais flexível e reduz o acoplamento. O Koin implementa DI através de um contêiner que gerencia a criação e o ciclo de vida dos objetos.
Instalação do Koin
Adicione a seguinte dependência ao arquivo build.gradle.kts:
// build.gradle.ktsdependencies { implementation("io.insert-koin:koin-core:3.5.3") // Para Android implementation("io.insert-koin:koin-android:3.5.3")}Conceitos Principais do Koin
- Módulo (module) — bloco onde as dependências são declaradas.
- Definição (definition) — forma de criar o objeto (single, factory, scoped).
- Contêiner (KoinApplication) — inicia e gerencia os módulos.
- Injeção (inject) — obtenção da dependência através de delegados ou funções.
Criação de Módulos e Declaração de Dependências
O Koin usa DSL para descrever os módulos. Vejamos um exemplo com um repositório e um serviço:
// Definimos a interface e a implementaçãointerface UserRepository { fun getUser(id: Int): String}
class UserRepositoryImpl : UserRepository { override fun getUser(id: Int) = "User #$id"}
class UserService(private val repository: UserRepository) { fun printUser(id: Int) { println(repository.getUser(id)) }}
// Módulo Koinval appModule = module { // single — cria uma única instância (singleton) single<UserRepository> { UserRepositoryImpl() } // factory — cria uma nova instância a cada solicitação factory { UserService(get()) }}Inicialização do Contêiner
Antes de usar as dependências, é necessário iniciar o Koin:
import org.koin.core.context.startKoin
fun main() { startKoin { modules(appModule) } // Agora podemos obter as dependências val service: UserService by inject() service.printUser(42)}Formas de Injeção de Dependências
- by inject() — obtenção preguiçosa (recomendado).
- get() — obtenção imediata.
- Construtor — o Koin passa automaticamente as dependências para o construtor.
Exemplo usando by inject():
class MyActivity : AppCompatActivity() { // Injeção preguiçosa private val repository: UserRepository by inject() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Usamos o repository }}Dependências com Escopo (Scoped)
Às vezes, é necessário criar uma dependência que viva dentro de um contexto específico (por exemplo, uma sessão de usuário). Para isso, usa-se scope:
val sessionModule = module { scope<UserSession> { scoped { UserSessionManager(get()) } }}Trabalhando com Corrotinas
O Koin suporta corrotinas através do módulo koin-core-coroutines. Exemplo de obtenção assíncrona:
import org.koin.core.component.KoinComponentimport org.koin.core.component.inject Também na biblioteca
Registro de Logs para PHP (Monolog)
Criptografia em Node.js: criptografia e hash com crypto
Trabalhando com S3 e armazenamentos em nuvem em Kotlin: AWS SDK e Ktor S3 Client
Autorização e Autenticação em Go (Golang): JWT, OAuth2 e Sessões