Você provavelmente já terminou seu curso agora, mas no caso de você ainda estar pesquisando, ou outra pessoa: rolando seu próprio DI é realmente muito simples no Android, uma vez que você sabe como fazer isso.
Criando o gráfico de dependência
Eu geralmente começo primeiro com uma classe de aplicativo personalizada (não se esqueça de registrá-lo no manifesto android), essa classe vai viver em todo o ciclo de vida do seu aplicativo android e é onde o seu código pode acessar suas dependências. Algo parecido com isto:
public class CustomApp extends Application {
private static ObjectGraph objectGraph;
@Override
public void onCreate() {
super.onCreate();
objectGraph = new ObjectGraph(this);
}
// This is where your code accesses its dependencies
public static <T> T get(Class<T> s) {
Affirm.notNull(objectGraph);
return objectGraph.get(s);
}
// This is how you inject mock dependencies when running tests
public <T> void injectMockObject(Class<T> clazz, T object) {
objectGraph.putMock(clazz, object);
}
}
(Affirm.notNull () apenas explode se algo é nulo, você não precisa usá-lo). As dependências reais estão todas na classe ObjectGraph que basicamente se parece com isto:
class ObjectGraph {
private final Map<Class<?>, Object> dependencies = new HashMap<>();
public ObjectGraph(Application application) {
// Step 1. create dependency graph
AndroidLogger logger = new AndroidLogger();
Wallet wallet = new Wallet(logger);
//... this list can get very long
// Step 2. add models to a dependencies map if you will need them later
dependencies.put(Wallet.class, wallet);
}
<T> T get(Class<T> model) {
Affirm.notNull(model);
T t = model.cast(dependencies.get(model));
Affirm.notNull(t);
return t;
}
<T> void putMock(Class<T> clazz, T object) {
Affirm.notNull(clazz);
Affirm.notNull(object);
dependencies.put(clazz, object);
}
}
Uso
Agora, onde quer que você esteja no seu aplicativo (em uma atividade, por exemplo), você pode injetar suas dependências assim:
private Wallet wallet;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
wallet = CustomApp.get(Wallet.class);
//...
}
Você pode usar o Dagger de algumas maneiras diferentes, mas o equivalente mais próximo do Dagger2 seria algo assim:
AppComponent appComponent = CustomApp.getAppComponent();
Wallet wallet = appComponent.getWallet();
Dependências com escopo
O que você estaria injetando aqui seria uma classe que tenha o escopo de nível application . Se você quer apenas um objeto escopo local que só existe enquanto você mantiver uma referência a ele em sua visão ou atividade, você faz exatamente a mesma coisa, mas o que você injeta é uma fábrica classe:
No ObjectGraph:
WalletFactory walletFactory = new WalletFactory(logger);
No seu fragmento, por exemplo:
Wallet wallet = CustomApp.get(WalletFactory.class).getNewWallet();
Teste
Tudo isso é feito para que você possa testar seu código da camada de visualização com facilidade. Por exemplo, se você deseja executar um teste de café expresso, crie o aplicativo, mas antes de mostrar a atividade, substitua a instância da carteira por uma simulação:
CustomApp.injectMockObject(Wallet.class, mockedWalletWith100Dollars);
Esta é a instância da carteira que será capturada pelo restante do seu código durante o teste.
De certa forma, este estilo de DI não é tão flexível quanto o Dagger2, mas eu acho que é muito mais claro - apenas não é necessário fazer o DI complicado, é na verdade uma coisa bastante básica. Esse estilo também resulta frequentemente em menos placa de caldeira do que usando uma estrutura DI (uma vez que você inclui classes de componentes e módulos).
Exemplos completos
Eu escrevi algo semelhante para 5 exemplos de aplicativos como parte de uma estrutura que publiquei (querendo manter as amostras tão acessíveis quanto possível - nem todo mundo gosta de Dagger). Você pode ver os exemplos completos aqui: link