Considering modules are all shared among one-another through the Dagger1 specification of complete=false, library=true
, you can receive the elements provided by the @Provides
methods through a constructor parameter, like so.
public class GetUserForUsernameTaskImpl
implements GetUserForUsernameTask {
public static final String TAG = GetUserForUsernameTaskImpl.class.getSimpleName();
private Realm realm;
private UserRepository userRepository;
public GetUserForUsernameTaskImpl(Realm realm, UserRepository userRepository) {
this.realm = realm;
this.userRepository = userRepository;
}
@Override
public RealmResults<UserRLM> getUsers() {
try {
RealmResults<UserRLM> users = userRepository.findAll(realm);
...
}
@Module(includes = {RepositoryModule.class, RealmModule.class})
public class DatabaseTaskModule {
@Provides
public GetUsersDatabaseTask getUsersDatabaseTask(Realm realm, UserRepository userRepository) {
return new GetUsersDatabaseTaskImpl(realm, userRepository);
}
}
However, you could also specify only one dependency (the Presenter
or the CustomApplication
instance) that holds the component graph, and use that component graph to inject your implementation classes.
public class GetUserForUsernameTaskImpl
implements GetUserForUsernameTask {
public static final String TAG = GetUserForUsernameTaskImpl.class.getSimpleName();
@Inject
public Realm realm;
@Inject
public UserRepository userRepository;
protected Presenter presenter;
private boolean isInjected = false;
public GetUserForUsernameTaskImpl(Presenter presenter) {
this.presenter = presenter;
}
@Override
public RealmResults<UserRLM> getUsers() {
if(!isInjected) {
presenter.getPresenterComponent().inject(this);
isInjected = true;
}
try {
RealmResults<UserRLM> users = userRepository.findAll(realm);
...
}
}
@Module(includes = {PresenterModule.class})
public class DatabaseTaskModule {
@Provides
public GetUsersDatabaseTask getUsersDatabaseTask(Presenter presenter) {
return new GetUsersDatabaseTaskImpl(presenter);
}
}
And that way, you'd only have to depend on the presenter's object graph, and not have to mess with constructor parameters.
Which one is a better approach?
EDIT: A clearer and concrete example I have in a not-too-well refactored project is the following:
@Module(includes = {ContextModule.class})
public class ClientAuthModule {
@Provides
public ClientAuthAuthenticator clientAuthAuthenticator(CustomApplication customApplication) {
return new ClientAuthAuthenticator(customApplication);
}
}
Then
public class CustomApplication
extends Application {
public static class InjectorInitializedEvent {
}
public static class InjectorInitializedEventProducer {
@Produce
public InjectorInitializedEvent produceEvent() {
return new InjectorInitializedEvent();
}
}
private ApplicationComponent applicationComponent;
@Override
public void onCreate() {
super.onCreate();
applicationComponent = Injector.INSTANCE.initializeApplicationComponent();
SingletonBus.INSTANCE.getBus().post(new InjectorInitializedEvent());
SingletonBus.INSTANCE.getBus().register(new InjectorInitializedEventProducer()); //OTTO bus, event producer
}
public ApplicationComponent getApplicationComponent() {
return this.applicationComponent;
}
}
Then
public class ClientAuthAuthenticator {
private CustomApplication customApplication;
@Inject
public PEMConverter pemConverter;
@Inject
public KeyPairCreator keyPairCreator;
@Inject
public PKCS10CsrCreator pkcs10CsrCreator;
@Inject
public KeyPairReader keyPairReader;
//...
public ClientAuthAuthenticator(CustomApplication customApplication) {
this.customApplication = customApplication;
SingletonBus.INSTANCE.getBus().register(this);
}
@Subscribe
public void onInjectorInitializedEvent(CustomApplication.InjectorInitializedEvent e) {
customApplication.getApplicationComponent().inject(this);
SingletonBus.INSTANCE.getBus().unregister(this);
}
...
The question: This way, all dependencies are provided from the application's component when the injector is ready, rather than through the constructor. But is this a good approach? Are there any caveats on the long-run?
EDIT2: I had the injector here, but it was pretty bad.
The one I have in my other project was better constructed.