Android dagger 2: зависимость не может быть предоставлена ​​без метода с аннотацией @ Provides

Зависимости Dagger 2:

implementation "com.google.dagger:dagger:2.15"
kapt "com.google.dagger:dagger-compiler:2.15"

Мой AppComponent:

@Singleton
@Component(modules = [
    DomainModule::class,
    DataModule::class,
    PresentationModule::class,
    ViewModelModule::class,
    RepositoriesModule::class
])
interface AppComponent {

    //reps
    fun topicsRep(): TopicsRepository
    fun countriesRep(): CountriesRepository
    fun loginRep(): LoginRepository
}

Мой класс ViewModelModule:

@Module
abstract class ViewModelModule {

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

    @Binds
    @IntoMap
    @ViewModelKey(LoginViewModel::class)
    internal abstract fun loginViewModel(viewModel: LoginViewModel): ViewModel

    @Binds
    @IntoMap
    @ViewModelKey(CountriesViewModel::class)
    internal abstract fun countriesViewModel(viewModel: CountriesViewModel): ViewModel
}

Мой ViewModelFactory:

   @Suppress("UNCHECKED_CAST")
@Singleton
class ViewModelFactory
@Inject constructor(private val viewModels: MutableMap<Class<out ViewModel>,
        @JvmSuppressWildcards Provider<ViewModel>>) :
        ViewModelProvider.Factory {

    override fun <T : ViewModel> create(modelClass: Class<T>): T = viewModels[modelClass]?.get() as T
}

@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)

И например мои CountryComponent и CountryModule:

@ActivityScope
@Component(modules = [CountryModule::class], dependencies = [AppComponent::class])
interface CountryComponent {

   fun inject(activity: SelectCountryActivity)
}

@Module
class CountryModule {

    @Provides
    @Singleton
    fun provideCountriesInteractor(rep: CountriesRepository)
             = SelectCountryInteractor(rep)
}

Чего я пытаюсь достичь - мне нужно внедрить экземпляр ViewModelFactory в свои действия и фрагменты. Мои модели просмотра содержат другие зависимости. Также пытаюсь разделить зависимости для каждого экрана.

После сборки получаю ошибку:

CountryComponent.java:10: error: 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

java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at ViewModelFactory.<init>(viewModels)
ViewModelFactory is injected at SelectCountryActivity.factory
SelectCountryActivity is injected at CountryComponent.inject(activity)

При установке ViewModelFactory как @Singleton возникает ошибка:

CountryComponent scoped with @ActivityScope may not reference bindings with different scopes:
@dagger.Component(modules = {CountryModule.class}, dependencies = {AppComponent.class})
@Singleton class ViewModelFactory
AppComponent.java:6: error: AppComponent scoped with @Singleton may not reference bindings with different scopes:
@dagger.Component(modules = {DomainModule.class, DataModule.class, PresentationModule.class, ViewModelModule.class, RepositoriesModule.class})

Есть ли причина отмечать ViewModel как Singleton или ActivityScope?

0
0
492
1

Ответы 1

Исправлено добавлением

fun viewModelFactory(): ViewModelFactory

на мой AppComponent. Также удален @Singleton из ViewModelFactory

Есть ли причина разместить фабрику модели представления в компоненте приложения вместо активности и фрагмента?

Vairavan 16.11.2018 02:54

@Vairavan, вы имеете в виду добавить зависимость ViewModelModule в CountryComponent или создать ViewModelComponent?

TooLazy 16.11.2018 09:37

не весь ViewModelModule, а только тот, который соответствует действию / фрагменту, обрабатываемому CountryComponent, например, почему фабрика модели представления должна жить дольше, чем активность, использующая фабрику?

Vairavan 16.11.2018 13:33

Не знаю, как это сделать правильно

TooLazy 26.11.2018 07:51

Модуль, обеспечивающий зависимость для активности / фрагмента, также может предоставлять фабрику. Таким образом, после того, как действие / фрагмент завершено, фабрика также будет собрана мусором.

Vairavan 26.11.2018 19:05

Другие вопросы по теме