0

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);
}
jairrab
  • 3
  • 1
  • 2
  • Any reason why you're using field injection? I just wrote an answer the other day about how to _not_ use it for reference. See here: https://stackoverflow.com/a/46779883/1837367 – David Medenjak Oct 18 '17 at 08:09
  • Your error seems to be because you try to inject `UpdateDisplay` in `@Singleton` scope but you provide it in `@ActivityScope`, so Dagger has no way to access the provides method. If this is the error, please close as duplicate for future reference. If it is not please include the *full error* as shown in the question. – David Medenjak Oct 18 '17 at 08:12

0 Answers0