Dagger 2.10/2.11 injecting Activity failing
android, dagger, dagger-2, dependency-injection
Solution
As specified in dagger android documentation:
Pro-tip: If your subcomponent and its builder have no other methods or supertypes than the ones mentioned in step #2, you can use @ContributesAndroidInjector to generate them for you. Instead of steps 2 and 3, add an abstract module method that returns your activity, annotate it with @ContributesAndroidInjector, and specify the modules you want to install into the subcomponent. If the subcomponent needs scopes, apply the scope annotations to the method as well.
Thus, we can get rid of `LoginSubcomponent` and perform following changes in `ActivityBindingModule`:
@Module
public abstract class ActivityBindingModule {
@ActivityScope
@ContributesAndroidInjector(modules = LoginActivityModule.class)
abstract LoginActivity loginActivity();
}
LoginActivityModule.java
@Module
abstract class LoginActivityModule {
@Binds
abstract Activity bindActivity(LoginActivity activity);
@Provides
@ActivityScope
static ViewUtils viewUtils(Activity activity) {
return new ViewUtils(activity);
}
}
Your custom application class:
public class MyApp extends DaggerApplication {
@Inject
DispatchingAndroidInjector dispatchingActivityInjector;
@Override
protected AndroidInjector applicationInjector() {
return DaggerAppComponent.builder().create(this);
}
}
Problem
I have been trying to, unsuccessfully, inject the Activity in a class ViewUtils. I have followed a couple of different posts but I can't seem to understand what am I missing in my implementation. I know this is probably a repetition of the posts below and I really apologize for that but I honestly cannot see what am I missing. These are the posts I've found: - Dagger 2.10 Android subcomponents and builders - How to create custom scoped modules in dagger 2.10 - https://google.github.io/dagger/subcomponents.html My implementation is as follows: AppComponent ``` @Component(modules = { AppModule.class, AndroidSupportInjectionModule.class, ActivityBindingModule.class }) @Singleton public interface AppComponent extends AndroidInjector<EmblyApp> { @Component.Builder abstract class Builder extends AndroidInjector.Builder<EmblyApp> {} } ``` ActivityBindingModule ``` @Module public abstract class ActivityBindingModule { @ContributesAndroidInjector abstract LoginActivity loginActivity(); } ``` LoginSubcomponent ``` @Subcomponent(modules = LoginSubcomponent.LoginActivityModule.class) public interface LoginSubcomponent extends AndroidInjector<LoginActivity> { @Subcomponent.Builder abstract class Builder extends AndroidInjector.Builder<LoginActivity> {} @Module abstract class LoginActivityModule { @Binds abstract Activity bindActivity(LoginActivity activity); @Provides @ActivityScope static ViewUtils viewUtils(Activity activity) { return new ViewUtils(activity); } } } ``` ViewUtils ``` public class ViewUtils { private final Activity activity; @Inject public ViewUtils(Activity activity) { this.activity = activity; } } ``` And the error i'm getting is: ``` Error:(14, 22) error: [dagger.android.AndroidInjector.inject(T)] android.app.Activity cannot be provided without an @Inject constructor or from an @Provides-annotated method. android.app.Activity is injected at com.emblyapp.app.ui.helpers.ViewUtils.<init>(activity) com.emblyapp.app.ui.helpers.ViewUtils is injected at com.emblyapp.app.ui.authentication.login.LoginActivity.viewUtils com.emblyapp.app.ui.authentication.login.LoginActivity is injected at dagger.android.AndroidInjector.inject(arg0) ``` What is wrong in here? Thanks for the help! Edit: I forgot to mention my LoginActivity has the injection with the AndroidInjection ``` @Override protected void onCreate(Bundle savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); } ```