I am new to Dagger 2 and has been making some good progress until recently. I have a fragment CalculatorFragment
which unloads all of the logic into it's Presenter
class, which has an interface ViewOps
as it's constructor that is already implemented by CalculatorFragment
.
CalculatorFragment.java
public class CalculatorFragment extends Fragment implements ViewOps {
@Inject PresenterOps Presenter
public View onCreateView(...){
//...
CalculatorApplication
.getApplicationComponent(getActivity())
.getCalculatorFinancialComponent(new CalculatorModule(this))
.inject(this);
//...
}
Everything was working fine until I decided to move the update display functions into a separate class and tried to inject it back into the Presenter
. The UpdateDisplay
class takes the same ViewOps
as a constructor.
Presenter.java
public class Presenter implements PresenterOps{
@Inject TextFunctions textFunctions;
@Inject ConversionFunctions conversionFunctions;
//ADDING THIS INJECT ANNOTATION CAUSED THE PROBLEM!!!
@Inject UpdateDisplay updateDisplay;
public Presenter(ViewOps viewOps) {
CalculatorApplication
.getApplicationComponent(getActivity()).inject(this);
}
public someFunctions(){
textFunctions.doSomething();
conversionFunctions.doSomething();
updateDisplay.doSomething();
}
}
My understanding with Dagger 2 is I need to create a module class that defines the methods that will create the dependencies to be injected. The problem below is with the method providesUpdateDisplay()
. Everytime I build the project, it calls out the following error:
Error:(21, 10) error: UpdateDisplay cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method. This type supports members injection but cannot be implicitly provided.
I thought I already provided an @Provides providesUpdateDisplay()
annotated method in the CalculatorModule
below.
CalculatorModule.java
@Module
public class CalculatorModule {
private CalculatorFragment calculatorFragment;
public CalculatorModule(CalculatorFragment calculatorFragment) {
this.calculatorFragment = calculatorFragment;
}
@Provides
@ActivityScope
ViewOps providesViewOps() {
return calculatorFragment;
}
@Provides
@ActivityScope
CalculatorFragment providesCalculatorFinancial() {
return calculatorFragment;
}
@Provides
@ActivityScope
PresenterOps providesPresenterOps() {
return new Presenter(calculatorFragment);
}
//ISN'T THIS SUPPOSE TO BE THE @Provides method
//THAT PROVIDES UpdateDisplay???
@Provides
@ActivityScope
UpdateDisplay providesUpdateDisplay() {
return new UpdateDisplay(calculatorFragment);
}
}
To add, if I do not do @Inject UpdateDisplay updateDisplay
, and simply create an instance of UpdateDisplay
in the Presenter
constructor and not injecting UpdateDislay
into the AppComponent
, then everything works back OK.
public Presenter(ViewOps viewOps) {
new UpdateDisplay(getViewOps());
}
The problem is I cannot simply call injection of UpdateDisplay
into the Presenter
that I want to.
Here's the UpdateDisplay
:
UpdateDisplay.java
public class UpdateDisplay {
@Inject ConversionFunctions conversionFunctions;
private final ViewOps viewOps;
public UpdateDisplay(ViewOps viewOps) {
CalculatorApplication
.getApplicationComponent(viewOps.getActivity())
.inject(this);
this.viewOps = viewOps;
}
public doSomething() {
//...
}
CalculatorApplication
public class CalculatorApplication extends Application {
private AppComponent component;
public static AppComponent getApplicationComponent(Context context) {
return ((CalculatorApplication) context.getApplicationContext()).component;
}
@Override
public void onCreate() {
super.onCreate();
component = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
}
}
These are the components:
AppComponent.java
@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
void inject(ActivityMain activityMain);
CalculatorComponent getCalculatorFinancialComponent(CalculatorModule module);
void inject(UpdateDisplay updateDisplay);
void inject(Presenter presenter);
}
CalculatorComponent.java
@ActivityScope
@Subcomponent(modules = {CalculatorModule.class})
public interface CalculatorComponent {
void inject(CalculatorFinancial calculatorFinancial);
}