I'm trying to use hilt to inject an implementation of a repository class(the interface lives in the domain
module, the implementation in the data
module with the data
module depending on the domain
one) but receiving an error when building the app. Here's my setup
In domain
module
interface RatesRepository {
fun getRates(): Single<Rates>
}
in data
module
class RatesRepositoryImpl @Inject constructor(
private val rateDataSource: CurrencyExchangeDataSource,
private val mapper: ExchangeResponseToRates
) : RatesRepository {
//..
}
@Module
@InstallIn(FragmentComponent::class)
interface DataModule {
@Binds
fun bindsRatesRepository(ratesRepositoryImpl: RatesRepositoryImpl): RatesRepository
}
and data declares domain as a dependency
EDIT: the error I'm receiving :
error: [Dagger/MissingBinding] com.basil.domain_converter.repository.RatesRepository cannot be provided without an @Provides-annotated method.
public abstract static class ApplicationC implements CurrenciesApp_GeneratedInjector,
^
com.basil.domain_converter.repository.RatesRepository is injected at
com.basil.domain_converter.usecase.GetRatesUseCase(ratesRepository)
javax.inject.Provider<com.basil.domain_converter.usecase.GetRatesUseCase> is injected at
com.basil.ui_converter.ui.RatesViewModel_AssistedFactory(getRatesUseCase)
com.basil.ui_converter.ui.RatesViewModel_AssistedFactory is injected at
com.basil.ui_converter.ui.RatesViewModel_HiltModule.bind(arg0)
java.util.Map<java.lang.String,javax.inject.Provider<androidx.hilt.lifecycle.ViewModelAssistedFactory<? extends androidx.lifecycle.ViewModel>>> is injected at
androidx.hilt.lifecycle.ViewModelFactoryModules.ActivityModule.provideFactory(…, viewModelFactories)
@dagger.hilt.android.internal.lifecycle.DefaultActivityViewModelFactory java.util.Set<androidx.lifecycle.ViewModelProvider.Factory> is requested at
dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.ActivityEntryPoint.getActivityViewModelFactory() [com.basil.example.CurrenciesApp_HiltComponents.ApplicationC → com.basil.example.CurrenciesApp_HiltComponents.ActivityRetainedC → com.basil.example.CurrenciesApp_HiltComponents.ActivityC]
The following other entry points also depend on it:
dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.FragmentEntryPoint.getFragmentViewModelFactory() [com.basil.example.CurrenciesApp_HiltComponents.ApplicationC → com.basil.example.CurrenciesApp_HiltComponents.ActivityRetainedC → com.basil.example.CurrenciesApp_HiltComponents.ActivityC → com.basil.example.CurrenciesApp_HiltComponents.FragmentC]
It seems you have a problem with your Scopes
.
You're Installing
your RatesRepository
in the FragmentComponent
, but you're trying to use it in the dependencies of a higher level. I can see you're trying to inject RatesRepository
in ViewModels
, and ViewModels
do not relate to FragmentComponent
but ActivityRetainedComponent
.
See this graph:
I would expect a Repository
should be maintained in the App
scope, so I would modify your setup to:
@Module
@InstallIn(ApplicationComponent::class)
interface DataModule {
@Binds
fun bindsRatesRepository(ratesRepositoryImpl: RatesRepositoryImpl): RatesRepository
}
If dependencies of RatesRepositoryImpl
have narrower scope, you can try ActivityRetainedComponent
instead of ApplicationComponent
.