我已经尝试过创建多个组件。首先将存储应用程序的主要部分,例如ViewModel的结构,上下文和其他设置。其他组件-每个屏幕的组件。因此,f.ex。我有FirstScreen。我试图用其ViewModel创建组件:
@Subcomponent(modules = [StoreModule::class])
@StoreScope
interface StoreComponent {
fun inject(activity: MainActivity)
fun inject(fragment: StoreFragment)
@Subcomponent.Builder
interface Builder {
fun build(): StoreComponent
}
}
因此,StoreViewModel作为其依赖项StoreRepository内置在StoreComponent的模块中:
@Module
abstract class StoreModule {
@Binds
@IntoMap
@ViewModelKey(StoreViewModelImpl::class)
abstract fun getStoreViewModel(viewModel: StoreViewModelImpl): ViewModel
@Binds
@StoreScope
abstract fun getStoreRepository(repository: StoreRepositoryImpl): StoreRepository
}
这是AppComponent:
@Component(modules = [
GsonModule::class,
RetrofitModule::class,
ViewModelsFactoryModule::class,
CiceroneModule::class
])
@Singleton
interface AppComponent {
fun getStoreComponentBuilder(): StoreComponent.Builder
}
在这里建立ViewModel的工厂:
@Module
abstract class ViewModelsFactoryModule {
@Target(AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
@Binds
abstract fun getViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
}
但是,当我尝试构建项目时,出现了错误,没有@ Provides-annonated方法,匕首无法将Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>
提供给ViewModelFactory-class。
error: [com.sagrishin.smartreader.di.components.StoreComponent.inject(com.sagrishin.smartreader.presentation.fragments.StoreFragment)] java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent {
^
java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at
com.sagrishin.smartreader.presentation.viewmodels.factory.ViewModelFactory.<init>(creators)
com.sagrishin.smartreader.presentation.viewmodels.factory.ViewModelFactory is injected at
com.sagrishin.smartreader.presentation.fragments.StoreFragment.viewModelsFactory
com.sagrishin.smartreader.presentation.fragments.StoreFragment is injected at
com.sagrishin.smartreader.di.components.StoreComponent.inject(fragment)
UPD:viewmodel工厂:
typealias ViewModelsProvidersMap =
Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
@Singleton
class ViewModelFactory : ViewModelProvider.Factory {
private val creators: ViewModelsProvidersMap
@Inject
constructor(creators: ViewModelsProvidersMap) {
this.creators = creators
}
override fun <T : ViewModel> create(modelClass: Class<T>): T {
var creator: Provider<out ViewModel>? = creators[modelClass]
if (creator == null) {
for ((key, value) in creators) {
if (modelClass.isAssignableFrom(key)) {
creator = value
break
}
}
}
if (creator == null) {
throw IllegalArgumentException("unknown model class $modelClass")
}
try {
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
答案 0 :(得分:0)
通过将ViewModelFactory.kt和ViewModelsFactoryModule.kt切换到Java,我解决了同样的问题。
ViewModelFactory.java
@Singleton
public class ViewModelFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
@Inject
ViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
this.creators = creators;
}
@NonNull
@SuppressWarnings("unchecked")
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
Provider<? extends ViewModel> creator = creators.get(modelClass);
if (creator == null) {
for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
if (modelClass.isAssignableFrom(entry.getKey())) {
creator = entry.getValue();
break;
}
}
}
if (creator == null) {
throw new IllegalArgumentException("unknown model class " + modelClass);
}
try {
return (T) creator.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
ViewModelsFactoryModule.java
@Module
abstract class ViewModelModule {
@NonNull
@Binds
@IntoMap
@ViewModelKey(StoreViewModelImpl.class)
abstract ViewModel bindLauncherViewModel(StoreViewModelImpl viewModel);
@NonNull
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory viewModelFactory);
}
答案 1 :(得分:0)
您不必切换到Java,只需使用kotlin 1.3.31
对其进行修复。 https://github.com/google/dagger/issues/1478#issuecomment-486712176
包括以下Jvm注释
Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
答案 2 :(得分:0)
No need to use @JvmSuppressWildcards. As the day of my Post my Kotlin version
is : '1.3.40'
Use dagger dependency in build.gradle
apply plugin: 'kotlin-kapt'
//Dagger dependencies
implementation 'com.google.dagger:dagger:2.22.1'
kapt 'com.google.dagger:dagger-compiler:2.22.1'
implementation 'com.google.dagger:dagger-android:2.22'
implementation 'com.google.dagger:dagger-android-support:2.22' // if you use the support libraries
kapt 'com.google.dagger:dagger-android-processor:2.22'
And for Java use the following dagger dependency
//Dagger dependencies
implementation 'com.google.dagger:dagger:2.22.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.22.1'
implementation 'com.google.dagger:dagger-android:2.22'
implementation 'com.google.dagger:dagger-android-support:2.22' // if you use the support libraries
annotationProcessor 'com.google.dagger:dagger-android-processor:2.22'
答案 3 :(得分:0)
您的依赖版本可能有所不同,例如您的核心/编译器版本为2.22或其他版本,但您的android版本为2.16,这也可能导致异常,请执行以下操作:
从这个
implementation 'com.google.dagger:dagger:2.22'
kapt 'com.google.dagger:dagger-compiler:2.22'
// For android
implementation 'com.google.dagger:dagger-android:2.16'
implementation 'com.google.dagger:dagger-android-support:2.16'
// if you use the support libraries
kapt 'com.google.dagger:dagger-android-processor:2.16'
对此
//Dagger 2
implementation 'com.google.dagger:dagger:2.22'
kapt 'com.google.dagger:dagger-compiler:2.22'
// For android
implementation 'com.google.dagger:dagger-android:2.22'
implementation 'com.google.dagger:dagger-android-support:2.22'
// if you use the support libraries
kapt 'com.google.dagger:dagger-android-processor:2.22'