Is it possible to inject something into a module?
I have 2 base modules / components:
@Component(modules = {OkHttpModule.class})
public interface OkHttpComponent extends AppComponent {
OkHttpClient provideOkHttpClient();
}
@Module
public class OkHttpModule {
@Provides
OkHttpClient provideOkHttpClient() {
return mHttpClient;
}
}
@Component(modules = {GsonModule.class})
public interface GsonComponent extends AppComponent {
Gson provideGson();
}
@Module
public class GsonModule {
@Provides
Gson provideGson() {
return mGson;
}
}
With this modules / components I want to create a 3rd module:
@Component(dependencies = {OkHttpComponent.class, GsonComponent.class},
modules = {RetrofitModule.class})
public interface RetrofitComponent extends AppComponent {
API provideAPI();
}
@Module
public class RetrofitModule {
@Inject OkHttpClient mHttpClient;
@Inject Gson mGson;
@Provides
VeentsMeAPI provideVeentsMeAPI() {
return mVeentsMeAPI;
}
}
But mHttpClient
and mGson
are not injected. Is it possible to inject something into a module? And if yes how?
I create the components like this:
okHttpComponent = DaggerOkHttpComponent.builder()
.okHttpModule(new OkHttpModule(this))
.build();
gsonComponent = DaggerGsonComponent.builder()
.gsonModule(new GsonModule())
.build();
retrofitComponent = DaggerRetrofitComponent.builder()
.retrofitModule(new RetrofitModule())
.okHttpComponent(okHttpComponent)
.gsonComponent(gsonComponent)
.build();
Components are essentially the glue that holds everything together. They are a way of telling Dagger 2 what dependencies should be bundled together and made available to a given instance so they can be used. They provide a way for a class to request dependencies being injected through their @Inject annotation.
Subcomponent can only have one parent.
For a fast read, a Component in Dagger is an unit which is essentially used to resolve dependencies. A Module is a sub-unit, providing dependencies, one or several of which can be used by a Component. A SubComponent is a type of Component which derives from a Component, inheriting the dependencies it already provides.
In my opinion, there isn't really a point to injecting into a module. All modules are declared as complete=false, library=true
as per the Dagger1 definition of modules, meaning you don't need to specify any real magic as long as you include the modules that are not contained within the component you are using, or make your component dependencies link to each other in such a way that each dependency you can inject is specified only in one component.
You will get the dependencies from other modules in constructor parameters. You need to include the module on the includes
list, or you need to have the module specified in your component within the same scope.
The right way to do it is this:
@Module
public class OkHttpModule {
@Provides
@ApplicationScope
public OkHttpClient okHttpClient() {
return new OkHttpClient();
}
}
@Module
public class GsonModule {
@Provides
@ApplicationScope
public Gson gson() {
return new Gson();
}
}
@Module(includes={GsonModule.class, OkHttpModule.class}) //look closely, this is the magic
public class RetrofitModule {
@Provides
@ApplicationScope
public VeentsMeAPI veentsMeAPI(Gson gson, OkHttpClient okHttpClient) { //dependencies!
return RestAdapter.Builder()
.setClient(new Client(okHttpClient))
.setConverter(new GsonConverter(gson))
.create(VeentsMeAPI.class);
}
}
And then it's
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationScope {}
And maybe even
@ApplicationScope
public class Something {
private final VeentsMeAPI veentsMeApi;
@Inject
public Something(VeentsMeAAPI veentsMeApi) {
this.veentsMeApi = veentsMeApi;
}
}
Then
@ApplicationScope
@Component(modules={RetrofitModule.class}) //contains all other modules/dependencies
public interface AppComponent {
OkHttpClient okHttpClient();
Gson gson();
VeentsMeAPI veentsMeAPI();
Something something();
void inject(SomeActivity someActivity);
}
and
Then you'd get the generated stuff and you'd have to build it together like so
AppComponent appComponent = DaggerAppComponent.create();
//use appComponent.inject(someActivity); with `void inject(Stuff someActivity);` methods defined in AppComponent
Component dependencies are the same as subcomponents, so those are for subscoping, and not for inheriting dependencies from the same scope. Dependencies of the same scope should be in the same component, just different modules.
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