dagger: Class keys into map don't work in Kotlin 1.3.30
Setup:
- AGP 3.3.x
- Dagger 2.21+
- Kotlin 1.3.30
- Gradle 5.3.1
Error:
e: C:\gradle\build\DaggerKotlin\app\tmp\kapt3\stubs\debug\net\xpece\test\daggerkotlin\TheComponent.java:8: error: [Dagger/MissingBinding] java.util.Map<kotlin.reflect.KClass<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.
public abstract interface TheComponent {
^
java.util.Map<kotlin.reflect.KClass<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
net.xpece.test.daggerkotlin.DaggerViewModelFactory(creators)
net.xpece.test.daggerkotlin.DaggerViewModelFactory is injected at
net.xpece.test.daggerkotlin.ViewModelModule.bindViewModelFactory(impl)
androidx.lifecycle.ViewModelProvider.Factory is injected at
net.xpece.test.daggerkotlin.MainActivity.vmf
net.xpece.test.daggerkotlin.MainActivity is injected at
net.xpece.test.daggerkotlin.TheComponent.inject(net.xpece.test.daggerkotlin.MainActivity)
Current state:
Injecting a Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
based on KClass<out ViewModel
keys produces an error.
Changing to Map<KClass
… doesn’t help.
Expected state:
Injecting a Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
based on KClass<out ViewModel
keys should work as before.
Workaround:
Migrate the class key annotation to Java.
Relevant code:
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
@Singleton
class DaggerViewModelFactory @Inject constructor(
private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
// ...
}
@Module
abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(impl: DaggerViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(ViewModelOne::class)
abstract fun bindViewModelOne(impl: ViewModelOne): ViewModel
@Binds
@IntoMap
@ViewModelKey(ViewModelTwo::class)
abstract fun bindViewModelTwo(impl: ViewModelTwo): ViewModel
}
@Component(modules = [ViewModelModule::class])
@Singleton
interface TheComponent {
fun inject(activity: MainActivity)
}
class MainActivity : Activity() {
protected val component by lazy {
DaggerTheComponent.create()
}
@Inject
protected lateinit var vmf: ViewModelProvider.Factory
protected val vm1: ViewModelOne by lazy { vmf.create(ViewModelOne::class.java) }
protected val vm2: ViewModelTwo by lazy { vmf.create(ViewModelTwo::class.java) }
override fun onCreate(savedInstanceState: Bundle?) {
component.inject(this)
super.onCreate(savedInstanceState)
}
}
Sample
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 83
- Comments: 37
Links to this issue
Commits related to this issue
- Downgrade kotlin to 1.3.21 https://github.com/google/dagger/issues/1478 — committed to sasfmlzr/DvachMovie by sasfmlzr 5 years ago
- Bump deps versions Can't update Kotlin version yet because of the following issue: https://github.com/google/dagger/issues/1478 — committed to ApplETS/Notre-Dame-v3 by Sonphil 5 years ago
- Update dependencies (#88) * Bump deps versions Can't update Kotlin version yet because of the following issue: https://github.com/google/dagger/issues/1478 * Move Resource to shared model packa... — committed to ApplETS/Notre-Dame-v3 by Sonphil 5 years ago
- Workaround in Java due to Dagger/Kotlin not playing well together as of now see: https://github.com/google/dagger/issues/1478 — committed to alteredworlds/posts by TomGilbert 5 years ago
The issue probably comes from Kotlin as it is the Kotlin update that stopped the code for working. I made a Kotlin issue just in case : https://youtrack.jetbrains.com/issue/KT-30979 (I was working on my own sample then saw your issue)
@VeegaP You switch the
ViewModelKey
from Kotlin to JavaThis is now fixed in kotlin 1.3.31 https://github.com/JetBrains/kotlin/blob/1.3.30/ChangeLog.md
I’m having the same issue on
kotlin_version = '1.3.41'
I still have the same issue. @bleeding182 Workaround doesn’t work for me.
1.3.71 same 🤔
Should be fixed in kotlin 1.3.31 (yet to be released) according to the kotlin issue linked above
I clear my gradle cache and rerun and the java solution is working now
I can confirm the Java workaround [1] works fine with Dagger 2.21 && 2.27 Gradle 5.4.1 && 6.1.1 && 6.3 Kotlin 1.3.70 && 1.3.71
[1] https://github.com/google/dagger/issues/1478#issuecomment-485976409
Still happening with 1.3.71 Dagger 2.72 AGP 4.0-beta04 Gradle 6.1.1
Changing to java doesn’t work. Why is this issue closed, it doesn’t seem to be resolved yet
@aldefy Same issue in x.50, x.60 and x.61
same in kotlin 1.3.50
Sometimes a build cache of kapt doesn’t track deleted kotlin files. Probably you have to not only clean build dir but delete build cache as well.
@vladkarpman Yup everything is fine on your end. I don’t know why it keeps crashing. I “fixed” this issue by downgrading to
org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.20
and using the Kotlin ViewModelKey class.