Description
Dagger version: 2.40
Sample project: https://github.com/ghus-raba/dagger-assisted-sample
Currently, annotating an assisted factory with scope like @Singleton
takes no effect and the factory can inject also dependencies from other scopes.
In the sample project there is an AppComponent
with @Singleton
scope and it has a subcomponent ActivityComponent
with @ActivityScope
. We try to inject dependencies to ViewModel
and try to ensure that only unscoped or @Singleton
scoped dependencies can be injected, as its lifecycle is longer that the one of Activity
.
When we do assisted injection manually, we can annotate the factory as @Singleton
and it will correctly be provided by AppComponent
. Trying to inject a dependency from @ActivityScope
results in compilation error with [Dagger/IncompatiblyScopedBindings]
:
class ManuallyAssistedViewModel constructor(
foo: Foo,
bar: Bar,
assisted: Int
) : ViewModel() {
@Singleton
class Factory @Inject constructor(
val fooProvider: Provider<Foo>,
val barProvider: Provider<Bar>,
) {
fun create(assisted: Int) = ManuallyAssistedViewModel(
fooProvider.get(),
barProvider.get(),
assisted
)
}
}
However, if we do the same with @AssistedFactory
, the @Singleton
annotation is ignored and an Activity
instance is injected.
class AssistedViewModel @AssistedInject constructor(
foo: Foo,
bar: Bar,
activity: Activity,
@Assisted assisted: Int
) : ViewModel() {
@Singleton // this does nothing
@AssistedFactory
interface Factory {
fun create(assisted: Int): AssistedViewModel
}
}
Both of the above factories are injected in an activity like this:
private lateinit var component: ActivityComponent
@Inject internal lateinit var manuallyAssistedViewModelFactory: ManuallyAssistedViewModel.Factory
@Inject internal lateinit var assistedViewModelFactory: AssistedViewModel.Factory
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
component = application.component.activityComponentFactory.build(this)
component.inject(this)
// ...
}
We can explicitly provide the AssistedViewModel.Factory
from AppComponent
by adding a provision method val assistedFactory: AssistedViewModel.Factory
, even if we do not use it and keep the injection as shown above.
It would be nice, if we could just use a scope annotation the same way as it is possible with manual way.