使用 KClass 类型绑定到地图
Binding Into Map With KClass Type
我正在尝试将 ViewModel
的子 class 绑定到映射中,它们的 KClass
类型:
@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
中,是我AppComponent
中的一个模块。所以 Dagger 应该能够提供我的 ViewModelFactory
所需的 Map<KClass<out ViewModel>, Provider<ViewModel>>
,但我无法弄清楚它为什么会崩溃。
我还尝试将 ViewModelKey
注释 class 切换为 Java,将 Class
作为构造函数参数而不是 KClass
。然后修改我的ViewModelFactory
依赖一个Map<Class<out ViewModel>, Provider<ViewModel>>
,但是还是出现同样的错误
在注释中使用 KClass
时,它实际上被编译为 Java 的 Class
。但实际问题是 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 编译器不支持通配符。您可以在此处看到类似的问题:
我正在尝试将 ViewModel
的子 class 绑定到映射中,它们的 KClass
类型:
@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
中,是我AppComponent
中的一个模块。所以 Dagger 应该能够提供我的 ViewModelFactory
所需的 Map<KClass<out ViewModel>, Provider<ViewModel>>
,但我无法弄清楚它为什么会崩溃。
我还尝试将 ViewModelKey
注释 class 切换为 Java,将 Class
作为构造函数参数而不是 KClass
。然后修改我的ViewModelFactory
依赖一个Map<Class<out ViewModel>, Provider<ViewModel>>
,但是还是出现同样的错误
在注释中使用 KClass
时,它实际上被编译为 Java 的 Class
。但实际问题是 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 编译器不支持通配符。您可以在此处看到类似的问题: