Android Studio 2.2.2
I have a NewsListModelImp
class which is the model in the MVP.
I want to inject my retrofit service into the model. However, as NewsListModelImp
doesn't contain any reference to a context or activity I cannot call getApplication()
. Which is what you would do if you were in a activity or fragment. I don't want to pass any context or activity in the constructor of NewsListModeImp
as that would have to come from the presenter and I want to avoid any android stuff there.
public class NewsListModelImp implements NewsListModelContract {
@Inject
NYTimesSearchService mNYTimesSearchService;
public NewsListModelImp() {
((NYTimesSearchApplication)getApplication()).getAppComponent().inject(this);
}
}
My Application class
public class NYTimesSearchApplication extends Application {
private AppComponent mAppComponent;
public void onCreate() {
super.onCreate();
/* Setup dependency injection */
createAppComponent();
}
private void createAppComponent() {
mAppComponent = DaggerAppComponent
.builder()
.retrofitModule(new RetrofitModule())
.build();
}
public AppComponent getAppComponent() {
return mAppComponent;
}
}
My provides module
@Module
public class RetrofitModule {
private Retrofit retrofit() {
return new Retrofit
.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
@Provides
@Singleton
public NYTimesSearchService providesNYTimesSearch() {
return retrofit().create(NYTimesSearchService.class);
}
}
My Appcomponent
@Singleton
@Component(modules = {RetrofitModule.class})
public interface AppComponent {
void inject(NewsListModelImp target);
}
Many thanks for any suggestions,
Dagger-2
works reccurently. So if insideActivity
(orFragment
) object is injected and it's constructor is properly annotated with@Inject
annotation, the constructor's parameters will be injected too.Suppose inside the application you would like to inject:
The constructor of
NyTimesPresenter
must be annotated with@Inject
:NewsListModelImp
constructor must also be annotated with@Inject
:Then everything will be injected properly.
Why the parameters should be passed to class as constructors' parameters? Such design pattern conforms
SOLID principles
. Object dependencies are injected into objects and not created inside it and such code is easily testable (in tests dependencies can be replaced ie. byMock
's)EXTRA INFO:
It is possible to inject objects implementing specific interfaces. Such technique is described here. In your case
NyTimesPresenter
can haveNewsListModelContract
as it's dependency instead ofNewsListModelImp
. To do this add another module to yourAppComponent
:AppComponent
method to provide concrete class implementing interface should look like:The implementation of
NyTimesPresenter
should change (just to replace concrete class with interface it implements):