Search code examples
javaandroiddependency-injectiondagger-2dagger

Dagger 2: inject an interface in a constructor


I'm trying to learn dagger 2 but I'm confused in injecting of constructor with interface. This is my below code :

MainActivity.java

public class MainActivity extends AppCompatActivity implements MainView {

    // this keyword of request dependency . At compiling process, dagger will look at all of these annotations
    //to create the exact dependency

    @Inject MainPresenter mainPresenter ;
    TextView textView ;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textview) ;
        DaggerPresenterComponent.create().inject(this);
        textView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mainPresenter.doThings(8555) ;
            }
        });

    }

    /**********************************/

    @Override
    public void invokeRandomViewMethod(String msg) {
        textView.setText(msg);
    }
}

MainPresenter.java

public class MainPresenter {

    private MainView mainView ;

    @Inject
    public MainPresenter(MainView mainView) {
        this.mainView = mainView;
    }

    public void doThings(int value){
        Random random = new Random();
        int rand= random.nextInt(value) ;
        if(mainView != null){
            mainView.invokeRandomViewMethod("You random number is "+rand);
        }
    }

public interface MainView {
    void invokeRandomViewMethod(String msg) ;
}
}

This is the Module :

@Module
public class PresenterModule {

    @Provides
        // this is the method that will provide the dependancy
    MainPresenter provideMainPresenter(MainView mainView){
        return new MainPresenter(mainView);
    }
}

And this is the Component

@Component (modules = PresenterModule.class)
public interface PresenterComponent {
    void inject(MainActivity activity) ;
}

When I run the code it shows me this error :

Error:(15, 10) error: com.imennmn.hellodagger2example.MainView cannot be provided without an @Provides-annotated method. com.imennmn.hellodagger2example.MainView is injected at com.imennmn.hellodagger2example.presenterInjection.PresenterModule.provideMainPresenter(mainView) com.imennmn.hellodagger2example.MainPresenter is injected at com.imennmn.hellodagger2example.MainActivity.mainPresenter com.imennmn.hellodagger2example.MainActivity is injected at com.imennmn.hellodagger2example.simpleInjection.DataComponent.inject(activity)

My Question is how I can provide the interface MainView by inject it with dagger and bind the MainPresenter and MainActivity ? Any help would be appreciated !


Solution

  • By following code:

    
        MainPresenter provideMainPresenter(MainView mainView) {
            return new MainPresenter(mainView);
        }
    
    

    You are telling dagger: "hey, whenever I ask you to inject MainPresenter, construct it using MainView". But dagger complaints, because you haven't specified how exactly he should build/acquire MainView.

    So, in your PresenterModule do this:

    
        @Module
        public class PresenterModule {
    
            MainView mainView;
    
            public PresenterModule(MainView mainView) {
                this.mainView = mainView;
            }
    
            @Provides
            MainPresenter provideMainPresenter() {
                return new MainPresenter(mainView);
            }
    
        }
    
    

    Then when building the component:

    
        DaggerPresenterComponent.builder()
                                .presenterModule(new PresenterModule(this))
                                .build();