绑定到KClass类型的地图
我想通过它们的KClass
类型将ViewModel
子类绑定到一个地图中:
@Module abstract class ViewModelModule { @Binds @IntoMap @ViewModelKey(MyViewModel::class) abstract fun bindsMyViewModel(viewModel: MyViewModel): ViewModel @Binds abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory }
但是我得到了Dagger编译错误:
e: ~/Example/app/build/tmp/kapt3/stubs/debug/com/example/app/injection/AppComponent.java:5: error: [dagger.android.AndroidInjector.inject(T)] java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method. e: e: public abstract interface AppComponent { e: ^ e: java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at e: com.example.app.ui.ViewModelFactory.<init>(creators) e: com.example.app.ui.ViewModelFactory is injected at e: com.example.app.injection.ViewModelModule.bindViewModelFactory(p0) e: android.arch.lifecycle.ViewModelProvider.Factory is injected at e: com.example.app.ui.MyFragment.setViewModelFactory(p0) e: com.example.app.ui.MyFragment is injected at e: dagger.android.AndroidInjector.inject(arg0)
上面的ViewModelModule
包含在我的AppModule
,它是我的AppModule
中的一个模块。 所以Dagger应该能够提供我的ViewModelFactory
所需的Map<KClass<out ViewModel>, Provider<ViewModel>>
,但我无法弄清楚它为什么会崩溃。
我也尝试将ViewModelKey
注解类切换到Java,将Class
作为构造函数参数而不是KClass
。 然后修改我的ViewModelFactory
依赖于一个Map<Class<out ViewModel>, Provider<ViewModel>>
,但是发生了同样的错误。
在注释中使用KClass
时,它实际上被编译为Java Class
。 但实际问题是java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>>
的通配符java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>>
java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>>
java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>>
了Kotlin编译器生成的java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>>
。
假设@ViewModelKey
被定义为
@MapKey annotation class ViewModelKey(val value: KClass<out ViewModel>)
您需要将您的注射网站定义为
Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
使用@JvmSuppressWildcards
将会阻止编译器生成通配符。
我实际上并不知道为什么Dagger编译器不支持通配符。 你可以在这里看到类似的问题: Dagger 2:如何注入Map <Class <? 扩展Foo>,Provider <? 延伸Foo >>