Reputation: 12009
I have 2 classes for which I want dependency injection to happen. Basically both need each other's objects to perform some task.
First class
public class AppMobilePresenter {
AppPresenter appPresenter;
@Inject
public AppMobilePresenter(AppPresenter appPresenter) {
this.appPresenter = appCMSPresenter;
}
}
Its module
@Module
public class AppMobilePresenterModule {
@Provides
@Singleton
public AppMobilePresenter providesAppMobilePresenter(AppPresenter appPresenter) {
return new AppMobilePresenter(appPresenter);
}
}
Second Class
public class AppPresenter {
AppMobilePresenter appMobilePresenter;
@Inject
public AppPresenter() {
}
@Inject
void setAppMobilePresenter(AppMobilePresenter appMobilePresenter){
this.appMobilePresenter=appMobilePresenter;
}
}
Its modules
@Module(includes = { AppMobilePresenterModule.class})
public class AppPresenterModule {
@Provides
@Singleton
public AppPresenter providesAppPresenter() {
return new AppPresenter();
}
}
I have a common component for both
@Singleton
@Component(modules = {AppPresenterModule.class})
public interface AppPresenterComponent {
AppPresenter appPresenter();
}
After building the component from my application class and running the application I get AppMobilePresenter object null in AppPresenter class. Is there also something else need to be done for method injection.
Upvotes: 1
Views: 1342
Reputation: 95774
Method injection doesn't happen when you call constructors, as you do in your @Provides methods; if you want method injection to happen, Dagger needs to call your @Inject-annotated constructor in its generated code.
It looks like you'd prefer constructor injection, which is safer anyway, but are trying for method injection just to avoid a dependency cycle. Unfortunately, that won't work. Instead, switch back to constructor injection and use the technique shown here:
@Singleton
public class AppMobilePresenter {
AppPresenter appPresenter;
@Inject
public AppMobilePresenter(AppPresenter appPresenter) {
this.appPresenter = appCMSPresenter;
}
}
@Singleton
public class AppPresenter {
Provider<AppMobilePresenter> appMobilePresenterProvider;
@Inject
public AppPresenter(Provider<AppMobilePresenter> appMobilePresenterProvider) {
this.appMobilePresenterProvider = appMobilePresenterProvider;
}
}
The code above can use your same Component, and does not require any Modules. The one caveat is that to get to AppMobilePresenter from AppPresenter, you'll need to call appMobilePresenterProvider.get()
, which you can call anywhere except for constructors and @Inject methods. This solves the construction problem: Dagger otherwise couldn't create AppMobilePresenter without first creating an AppPresenter, and couldn't create AppPresenter without first creating AppMobilePresenter. It can create a Provider, though, and provide the instance when you call it later.
If future readers really need field or method injection, they can leave your @Inject constructors and methods alone while removing the Modules and switching to method-inject a Provider<AppMobilePresenter>
, which is necessary because method injection has the same construction-order dependency cycle concerns that constructor injection does.
Upvotes: 1