I'm using dagger 2.11 and it's not possible to inject Views out of the box, but I managed to do so:
BindingModule:
@Module(subcomponents = {...})
public abstract class ViewBindingModule {
@Binds
@IntoMap
@ViewKey(MyView.class)
abstract AndroidInjector.Factory<? extends BaseView> myView(MyViewSubComponent.Builder builder);
}
MyViewSubComponent:
@Subcomponent(modules = MyViewModule.class)
public interface MyViewSubComponent extends AndroidInjector<MyView> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MyView> {}
}
MyViewModule:
@Module
public abstract class MyViewModule extends ViewModule<MyView> {
public MyViewModule(MyView view) {
super(view);
}
}
ViewModule:
@Module
public abstract class ViewModule<V extends View> {
protected final V view;
public ViewModule(V view) {
this.view = view;
}
@Provides
@ViewScope
V provideView() {
return view;
}
}
BaseView:
ViewInjection.inject(this);
ViewInjection is pretty much a copy from other Injectors.
Now, I've an Activity, a CustomView and a BaseViewModel. My BaseViewModel contains an Object which needs an instance of AppCompatActivity.
I'm provinding it as fallow:
ActivityBindingModule:
@Module
public abstract class ActivityBindingModule {
@ActivityScope
@ContributesAndroidInjector(modules = MyActivityModule.class)
abstract MyActivity activity();
}
MyActivityModule
@Module
public abstract class MyActivityModule {
@Binds
abstract AppCompatActivity activity(MyActivity activity);
}
The object who needs the context:
@Inject
public Object(AppCompatActivity activity, ...)
BaseViewModel:
public BaseViewModel(Object object,...)
ViewModel (extends BaseViewModel):
@Inject
public ChildViewModel(Object object,...){super(object,...);...}
This configurations works pretty well when injecting my BaseViewModel inside the Activity (the "View"), but if I want to provide a BaseViewModel to a View (@Inject BaseViewModel inside a BaseView
) I'll have a problem because my Object needs an Activity provided by the ActivityBindingModule/MyActivityModule which has @ActivityScope
and not @ViewScope
:
Error:(27, 1) error: [dagger.android.AndroidInjector.inject(T)] android.support.v7.app.AppCompatActivity cannot be provided without an @Inject constructor or from an @Provides-annotated method.
android.support.v7.app.AppCompatActivity is injected at
com.myapp.MyObject.<init>(activity, …)
com.myapp.MyObject is injected at
com.myapp.MyViewModel.<init>(object, …)
com.myapp.MyViewModel is injected at
com.myapp.MyViewModel.mMyViewModel
com.myapp.MyView is injected at
dagger.android.AndroidInjector.inject(arg0)
A binding with matching key exists in component: com.myapp.di...ActivityBindingModule_MyActivity.MyActivitySubcomponent
...
I don't know if I'm being clear here, a bit confusing perhaps, but how can I achieve this?
Thanks for your time.