I am working in the new Android dagger 2.11 implemtnation; I am getting this error in runtime :
MainModule must be set.
I have one Activity with it's presenter injected in mainModule + multiple fragments( bottom view tabs)
I added ArticlesFragment as an example.
MainModule.java
@Module public abstract class MainModule {
@FragmentScoped
@ContributesAndroidInjector(modules = ArticlesFragment.class) abstract ArticlesFragment articlesFragment();
@Provides
@ActivityScoped static String provideTaskId(MainActivity activity) {
return activity.getIntent().getStringExtra(""); }
@ActivityScoped
@Provides
public PresenterFactory<MainContract.Presenter> providePresenterFactory() { return MainPresenter::new; }
ActivityBindingModule.java : addded to the appComponent
@ActivityScoped @ContributesAndroidInjector(modules = MainModule.class)
abstract MainActivity mainActivity();
Hey @vestrel00,
can you check this one ? I used your multiple fragments method.
@alouanemed I need to see more of your code. More specifically, I need to see the following;
android.app.ApplicationTake a look at this gist for an overview. Maybe you will see something missing or incorrect in your setup.
you can also look at the Architecture Blueprints which has the same setup as you https://github.com/googlesamples/android-architecture/tree/todo-mvp-dagger/todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/di
Thanks for the reply.
@digitalbuddha , I've checked the links you provided but couldn't figure it out.
Can you check this gist here I put all the files you requested? @vestrel00
https://gist.github.com/alouanemed/68e1e1aa27fe8749bb51efbbfa004d7d
@alouanemed, I took a look at your gist. Unfortunately, I'm unable to figure out the issue. Anyways, as per @digitalbuddha's comment, your code seems to be using the same structure as the google sample architecture blueprints, which may be different that the structure of my example project.
Wish you luck in fixing this issue though!
Isn't the problem that you're using an instance method provide in an abstract class?
Change @ActivityScoped
@Provides
public PresenterFactory<MainContract.Presenter> providePresenterFactory() { return MainPresenter::new; }
to static and it should probably work
@vestrel00 So I changed the modules to non-abstract classes and it worked.
and for fragments I created a class similar to ActivibityBindingModule.java and added it to appComponent so dagger can generate subcomponents for me.
Module public abstract class FragmentBindingModule {
@FragmentScoped @ContributesAndroidInjector(modules = ArticlesModule.class)
abstract ArticlesFragment articlesFragment();
.....
}
AppComponent :
@Singleton @Component(modules = {
AppModule.class, ActivityBindingModule.class, FragmentBindingModule.class,
AndroidSupportInjectionModule.class,
AppModule.class, NetworkModule.class, DataModule.class
}) public interface HarvestOrderComponent extends AndroidInjector<HarvestOrderApp> {
...
}
As @liminal pointed out it's presenter provide method 's fault. I couldn't find a way to make it abstract and let Dagger provide it :/
@ActivityScoped @Provides public PresenterFactory<MainContract.Presenter> providePresenterFactory() {
return MainPresenter::new;
}
Is there any better approach to improve this ? Thanks :)
@alouanemed it'll work if you just make it static. having an instance method means you have to have an instance of the module. If the provider-method is static then dagger can use it without requiring an instance of the module. So just changing it to
@ActivityScoped @Provides public static PresenterFactory<MainContract.Presenter> providePresenterFactory() {
return MainPresenter::new;
}
should work fine
Good to see this issue is resolved. This made me realize that there were only 2 places (1, 2) where I demonstrated how to use @Provides instead of @Binds in abstract module classes. Furthermore, I didn't at all discuss this in my article, which I'll now update with these discussions.
Thanks for bringing this up @alouanemed. Good eyes there @liminal!
UPDATE:
Someone asked me the same question. I answered the same issue with more in-depth explanations here: link
Most helpful comment
@alouanemed it'll work if you just make it static. having an instance method means you have to have an instance of the module. If the provider-method is static then dagger can use it without requiring an instance of the module. So just changing it to
@ActivityScoped @Provides public static PresenterFactory<MainContract.Presenter> providePresenterFactory() { return MainPresenter::new; }should work fine