Android e Injeção de Dependências
Eu considero a injeção de dependências crucial para qualquer código OO, e em se tratando de Aplicativos Android a injeção é interessante não somente para injeção de coisas como Services, mas também com injeção de Views ( e Fragments ).
A injeção de dependências também permite aumentar a testabilidade do seu código, quando por exemplo você pode facilmente trocar uma dependência de objeto por um Mock.
A injeção de Dependências não é apenas sobre testes, mas muito além. Ela provê um melhor reuso e intercâmbio de módulos por toda a sua aplicação. Também permite mudar o objeto a ser injetado conforme o ambiente, usando por exemplo um
DevLoggongModule em desenvolvimento e um ProdLoggingModule em Produção.
Usando o Dagger
Fazendo uma rápida pesquisa na web, a maioria dos resultados apontam para o Dagger como sendo a melhor opção. O Dagger é um projeto Open Source da Square, uma empresa que faz muitas coisas legais e de graça para o Android.
O Dagger é um biblioteca bem leve de injeção de dependências que implementa o padrão Java para anotações JSR-300 como @Inject e @Singleton.
O Dagger constrói instancias da classes de sua aplicação e satisfaz as suas dependências usando a Anotação javax.inject.Inject para identificar quais construtores ou campos estamos interessados.
Usando a anotação @Inject no construtor o Dagger irá criar uma nova instancia de objeto, e quando esta instancia for requisitada, o Dagger irá obter os parâmetros necessários e invocar o construtor.
class Usuario {
private final Perfil perfil;
@Inject
public Usuario(Perfil perfil){
this.perfil = perfil;
}
}
Mas você pode querer injetar os campos diretamente, para isso basta anotar os atributos da classe.
class Usuario {
@Inject
Perfil perfil;
@Inject
Endereco endereco;
public Usuario(){
}
}
Satisfazendo as Dependências
Por padrão o Dagger satisfaz todas as dependências de objetos que você requisitar. Se você pedir uma nova instancia de carro, então o objeto carro será chamada pelo seu construtor os campos anotados serão injetados, retornando um objeto completo.
Porém o Dagger não funciona em algumas situações.
Não Constrói Interfaces.
Classes de Terceiros não pode ser anotadas.
Objetos Configurados devem ser configurados pode você mesmo.
Para esses casos onde o @Inject é insuficiente ou inoperante, use a anotação @Provides.
Todos os métodos anotados com @Provides devem estar dentro de uma classe @Module.
@Module
class ApplicationModule{
@Provides
pubic Perfil providePerfil() {
return new PerfilUsuarioPremium();
}
@Provides
pubic Usuario providesUsuario(Perfil perfil) {
return new Usuario(perfil);
}
}
Por convenção usa-se o prefixo provide no nome de cada método provedor e o sufixo Module em cada classe de módulo.
Usando em uma aplicação Android
As suas classes de módulos precisam ser inicializadas e injetadas dentro de um ObjectGraph. O melhor local para realizar esta tarefas é em uma classes Application customizada.
public class Application extends android.app.Application {
private ObjectGraph objectGraph;
@Override
public void onCreate() {
super.onCreate();
objectGraph = ObjectGraph.create(new ApplicationModule());
}
public ObjectGraph getObjectGraph() {
return objectGraph;
}
}
Para poder injetar em suas activities como dependências, você precisará invocar o método inject do objeto ObjectGraph.
public abstract class BaseActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((Application) getApplication()).getObjectGraph().inject(this);
}
}
Depois de feito isso suas activities estão prontas para serem injetadas em qualquer outro objeto.
public class MainActivity extends BaseActivity {
@Inject
Usuario mUsuario;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUsuario.facaAlgo(...);
}
}
O Dagger possui muitas funcionalidades a mais que essas, e você pode conferir no site do Desenvolvedor.
Comments