I'm seeing some code where a SubComponent.Builder
is being injected. For instance:
class MyClass @Inject constructor(val mySubcomponentBuilder: MySubComponent.Builder) {
fun someFunc(knownAtRuntime: String) {
mySubcomponentBuilder.withSomethingIKnowAtRuntime(knownAtRuntime).build()
}
}
Why do we (and where/when should we) do this (i.e. inject subcomponent.builders)?
Is this sort of like assisted injection where we can provide instances that are needed on the graph that we only know during runtime?
Yes, a subcomponent builder is sort of like assisted injection, but for a whole subgraph of injectable Dagger dependencies.
What are subcomponents?
Subcomponents are additional components that derive from parent components. In Guice they are analogous to child injectors; in Dagger 1 they are analogous to subgraphs. They let you add additional bindings on top of the parent bindings, as specified through additional modules.
In the sense that they allow bindings from different graphs, they can be compared to component dependencies, but they are generated at the same time as the parent component and can transparently use bindings defined in the parent component. The dagger.android and Hilt packages both use subcomponents.
Each component can have their own scope, and subcomponents aren't an exception: you might see a
@Singleton ApplicationComponent
with a subcomponent of@RequestScope RequestComponent
for servers or@ActivityScope ActivityComponent
for Android. Each request or activity would get their own component instance. That would let you inject a@RequestScoped MetricsService
or@ActivityScoped User
, which would be the same instance within the same request/activity but different instances between the requests/activities.What are subcomponent builders?
Subcomponents might require modules to be instantiated if they have non-empty constructors, or they might require instances to be bound through
@BindsInstance
. SubcomponentBuilder
s allow you to specify those just like you would for a Component Builder.You also have the choice of using a Subcomponent.Factory, analogous to Component.Factory but with all of the Builder parameters as the arguments to one method call.
Why would I inject subcomponent builders? What are the alternatives?
Though you can declare subcomponents as factory methods specified on the parent component, this prevents Dagger from pruning unused dependencies because it can't see who is requesting the subcomponent. By declaring subcomponents on modules and injecting their builders into the graph, Dagger can remove entire subcomponents if you don't call them at all.