[AssistedInject] Allow scoping of AssistedFactory with annotations
See original GitHub issueDagger 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.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:11
- Comments:15 (4 by maintainers)
Top GitHub Comments
Yes, that sounds like a nice approach to me and I like it more than having a provision method on component that is not used at all.
So I had a go at the Dagger SPI plugin for validating injection of viewmodels if anyone is interested:
Thanks for looking into it, and yea, that is kind of weird, but probably not worth the effort to debug given it is so long ago and it would have been a bug anyway for that to require a scope annotation.