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 !
Definition. Constructor Injection is the act of statically defining the list of required Dependencies by specifying them as parameters to the class's constructor. The constructor signature is compiled with the type and it's available for all to see.
Dependency Injection, or DI in short, is a design pattern that allows to delegate the creation of objects and their dependencies to another object or framework. It is gaining a lot of interest in Android application development. This post shows how to inject objects using Dagger 2 through a console app.
The injector class injects dependencies broadly in three ways: through a constructor, through a property, or through a method. Constructor Injection: In the constructor injection, the injector supplies the service (dependency) through the client class constructor.
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();
Your provideMainPresenter
implicitly depends on a MainView
. Dagger has no way to get it. You need to add a method to provide it:
@Module
public class PresenterModule {
@Provides
MainView provideMainView(){
// Provide MainView here somehow so Dagger can use this to create a MainPresenter
}
@Provides
// this is the method that will provide the dependancy
MainPresenter provideMainPresenter(MainView mainView){
return new MainPresenter(mainView);
}
}
Add abstract module with @Binds
annotation, look at my impl of : AbstractTestSettingsFragmentModule.java
TestFragment.java
public class TestFragment extends Fragment{
@Inject TestFragmentContract.Presenter mPresenter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidSupportInjection.inject(this);
}
}
TestFragmentPresenterImpl.java
public class TestFragmentPresenterImpl implements TestFragmentContract.Presenter {
@Inject
public TestFragmentPresenterImpl(){
}
}
AbstractTestSettingsFragmentModule.java
@Module
public abstract class AbstractTestSettingsFragmentModule {
@Binds
@NonNull
public abstract TestSettingsFragmentContract.Presenter testSettingsFragmentPresenterImpl(TestSettingsFragmentImpl presenter);
}
ContributesModule.java
@Module
public abstract class ContributesModule {
@ContributesAndroidInjector(modules = {AbstractTestSettingsFragmentModule.class})
abstract TestSettingsFragment testSettingsFragment();
}
AppComponent.java
@Singleton
@Component(
modules = {
AndroidSupportInjectionModule.class,
ContributesModule.class,
AppModule.class,
})
public interface AppComponent extends AndroidInjector<DaggerApplication> {
void inject(TheApplication theApplication);
@Override
void inject(DaggerApplication instance);
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application application);
AppComponent build();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With