Переплет в карту с типом KClass
Я пытаюсь привязать подклассы ViewModel
к карте их типами 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
. Поэтому кинжал должен иметь возможность Map<KClass<out ViewModel>, Provider<ViewModel>>
, требуемый моим ViewModelFactory
, но я не могу понять, почему он сбой.
Я также попытался переключить класс аннотации ViewModelKey
на Java, взяв Class
как параметр конструктора вместо KClass
. Затем изменил мой ViewModelFactory
, чтобы он зависел от a Map<Class<out ViewModel>, Provider<ViewModel>>
, но произошла одна и та же ошибка.
Ответы
Ответ 1
При использовании KClass
в аннотации он фактически скомпилируется в Java Class
. Но актуальной проблемой является подстановочный знак в java.util.Map<kotlin.reflect.KClass<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>>
, который генерирует компилятор Kotlin.
Предполагая, что @ViewModelKey
определяется как
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
Вам нужно определить сайт для инъекций как
Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
Использование @JvmSuppressWildcards
не даст компилятору создавать подстановочные знаки.
Я действительно не знаю, почему подстановочные знаки не поддерживаются компилятором Dagger. Вы можете увидеть аналогичную проблему здесь: Кинжал 2: Как ввести карту < Class <? расширяет Foo > , Provider <? → →