Я пытался создать несколько компонентов.Сначала будут храниться основные части приложения, такие как ViewModel's Fabric, Context, другие настройки.Другие компоненты - компонент на экран.Так, напримерУ меня есть 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
}
Но, когда я пытаюсь построить проект, у меня возникает ошибка, из-за которой кинжал не может предоставить Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>
в ViewModelFactory-классебез @ Предоставляет метод, анонированный.
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: фабрика представления модели:
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)
}
}
}