I have 3 repositories:
interface MainRepository {
...
}
interface LocalRepository {
...
}
interface WebRepository {
...
}
Each Repository has it's own implementation:
@Singleton
class MainRepositoryImpl @Inject constructor(
private val localRepository: LocalRepository,
private val webRepository: WebRepository
) : MainRepository {
...
}
@Singleton
class LocalRepositoryImpl @Inject constructor(
private val localMapper: LocalMapper
private val popularMovieDao: PopularMovieDao
) : LocalRepository {
...
}
@Singleton
class WebRepositoryImpl @Inject constructor(
private val webMapper: WebMapper,
private val popularMovieApi: PopularMovieApi
) : WebRepository {
...
}
As you can see, MainRepository
needs to have both other repositories injected into it, however,I can't really figure out how to do it.
Of course I can inject it with type of LocalRepositoryImpl
or WebRepositoryImpl
but I want to inject it with type of LocalRepository
or WebRepository
for more generalized approach.
Here is the module that I tried writing:
@InstallIn(ApplicationComponent::class)
@Module
object Module {
@Singleton
@Provides
fun provideWebRepository(): WebRepository {
return WebRepositoryImpl(mapper = WebMapper(), popularMovieApi = PopularMovieApi.getInstance())
}
@Singleton
@Provides
fun provideLocalRepository(): LocalRepository {
return LocalRepositoryImpl(mapper = LocalMapper(), // Here I can't really
// figure out how to get @Dao since it requires DB
// which requires context and etc
// which makes me think that I've got completely wrong approach to this)
}
}
My Module of LocalData:
@InstallIn(ApplicationComponent::class)
@Module
object LocalDataSourceModule {
@Singleton
@Provides
fun provideMainDatabase(@ApplicationContext context: Context): MainDatabase = MainDatabase.getInstance(context)
@Provides
fun providePopularMovieDao(mainDatabase: MainDatabase): PopularMovieDao = mainDatabase.popularMovieDao()
}
My Module of WebData:
@InstallIn(ApplicationComponent::class)
@Module
object RemoteDataSourceModule {
@Singleton
@Provides
fun providePopularMovieApi(): PopularMovieApi = PopularMovieApi.getInstance()
}
How do I properly Inject Implementations that I have (LocalRepositoryImpl
& WebRepositoryImpl
) while maintaining types of interfaces(LocalRepository
& `WebRepository)??
Use @Binds
. Instead of your object Module
use following module:
@InstallIn(ApplicationComponent::class)
@Module
interface Module {
@Binds
fun bindWebRepository(repository: WebRepositoryImpl): WebRepository
@Binds
fun bindLocalRepository(repository: LocalRepositoryImpl): LocalRepository
}
It tells Dagger that if you need WebRepository
dependency then it must provide WebRepositoryImpl
and the same for LocalRepository
and LocalRepositoryImpl
.
What is the use case for @Binds vs @Provides annotation in Dagger2