用KClass类型绑定到映射 [英] Binding Into Map With KClass Type

查看:289
本文介绍了用KClass类型绑定到映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过KClass类型将ViewModel的子类绑定到映射中:

I am trying to bind subclasses of ViewModel into a map by their KClass types:

@Module abstract class ViewModelModule {

    @Binds @IntoMap @ViewModelKey(MyViewModel::class)
    abstract fun bindsMyViewModel(viewModel: MyViewModel): ViewModel

    @Binds abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

}

但是我收到Dagger编译器错误:

But I am getting Dagger compiler error:

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>>,但是我无法弄清楚为什么它崩溃了.

The above ViewModelModule is included in my AppModule, which is a module in my AppComponent. So Dagger should be able to provide the Map<KClass<out ViewModel>, Provider<ViewModel>> required by my ViewModelFactory, but I cannot figure out why it is crashing.

我还尝试将ViewModelKey注释类切换到Java,将Class用作构造函数参数而不是KClass.然后将我的ViewModelFactory修改为依赖于Map<Class<out ViewModel>, Provider<ViewModel>>,但是发生了相同的错误.

I also tried switching the ViewModelKey annotation class over to Java, taking a Class as a constructor parameter instead of a KClass. Then modified my ViewModelFactory to depend on a Map<Class<out ViewModel>, Provider<ViewModel>>, but the same error occurred.

推荐答案

在注释中使用KClass时,实际上已编译为Java的Class.但是实际的问题是Kotlin编译器正在生成的java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>>通配符.

When using KClass in an annotation, it actually gets compiled to Java's Class. But the actual issue is the wildcard in java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>> that the Kotlin compiler is generating.

假设@ViewModelKey被定义为

@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)

您需要将注射部位定义为

You'll need to define your injection site as

Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>

使用@JvmSuppressWildcards将阻止编译器生成通配符.

Using @JvmSuppressWildcards will prevent the compiler from generating wildcards.

我实际上不知道,为什么Dagger编译器不支持通配符.您可以在此处看到类似的问题:

I don't actually know, why wildcards are not supported by the Dagger compiler. You can see a similar issue here: Dagger 2: How to inject Map<Class<? extends Foo>, Provider<? extends Foo>>

这篇关于用KClass类型绑定到映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆