Sobes.tech
Middle

Para que é que se utiliza a injeção de dependências em aplicações Android?

sobes.tech IA

Resposta da IA

A injeção de dependências (DI) é usada em aplicações Android para decompor o código, melhorar a testabilidade e facilitar a refatoração. Permite que os componentes obtenham dependências de fontes externas em vez de as criarem por si próprios.

Os principais objetivos do uso de DI em Android:

  • Acoplamento reduzido: Os componentes tornam-se menos ligados entre si. Alterar uma dependência não requer modificar o componente que a utiliza.
  • Testabilidade: É fácil substituir implementações de teste (mocks, fakes) ao escrever testes unitários.
  • Gestão do ciclo de vida: Os frameworks DI podem gerir a criação e destruição de objetos, garantindo ciclos de vida adequados para as dependências, especialmente relevante no Android com seus ciclos de vida específicos de Activities, Fragments, etc.
  • Reutilização: As dependências podem ser facilmente reutilizadas por diferentes componentes da aplicação.
  • Simplificação do código: O código torna-se mais limpo e compreensível, pois não é necessário criar e passar dependências manualmente através de construtores ou setters.

Exemplos de frameworks DI em Android: Hilt (recomendado pelo Google), Dagger, Koin.

Exemplo (pseudocódigo sem DI):

// Classe que cria uma dependência internamente
class UserRepository {
    private val apiService = ApiService() // Criação interna de dependência

    fun getUser(id: Int): User {
        return apiService.fetchUser(id)
    }
}

class ApiService {
    fun fetchUser(id: Int): User {
        // Lógica para obter dados
        return User(id, "John Doe")
    }
}

data class User(val id: Int, val name: String)

Exemplo (pseudocódigo com DI):

// Classe que recebe a dependência através do construtor
class UserRepository(private val apiService: ApiService) {

    fun getUser(id: Int): User {
        return apiService.fetchUser(id)
    }
}

class ApiService {
    fun fetchUser(id: Int): User {
        // Lógica para obter dados
        return User(id, "Jane Doe")
    }
}

data class User(val id: Int, val name: String)

// Em algum lugar no código, onde ocorre a configuração de DI:
// val apiService = ApiService()
// val userRepository = UserRepository(apiService)

No último exemplo, UserRepository não sabe como criar ApiService, ele simplesmente a recebe de fora. Isso facilita substituir ApiService por uma versão de teste ao testar UserRepository.