I have these Repositories dependent on DataSources.
class LocationRepository: Repository<String>(LocationDataSource())
class ItemRepository: Repository<String>(ItemDataSource())
I would like to inject the Repository class with Hilt like this to prevent code duplication.
abstract class Repository<T> {
@Inject lateinit var dataSource: DataSource<T>
...
}
I have tried this, but am not sure how to get Hilt to use the right ones.
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class ItemDataSourceAnnotation
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class LocationDataSourceAnnotation
@Module
@InstallIn(SingletonComponent::class)
object DataSourceModule {
@ItemDataSourceAnnotation
@Provides
@Singleton
fun provideItemDataSource(): DataSource{
return ItemDataSource()
}
@LocationDataSourceAnnotation
@Provides
@Singleton
fun provideLocationDataSource(): DataSource{
return LocationDataSource()
}
}
@Module
@InstallIn(SingletonComponent::class)
object RepositoryModule {
@Provides
@Singleton
fun providesItemRepository(
@ItemDataSourceAnnotation itemDataSource: ItemDataSource
): ItemRepository {
return ItemRepository()
}
@Provides
@Singleton
fun providesLocationRepository(
@LocationDataSourceAnnotation locationDataSource: LocationDataSource
): LocationRepository {
return LocationRepository()
}
}
CodePudding user response:
If what you want is to avoid having the data source field in each repository subclass, you could add a data source type parameter and val to Repository:
class Repository<ValueT, DataSourceT>(val dataSource: DataSourceT) {
...
}
class LocationRepository: Repository<Location, LocationDataSource> @Inject constructor(dataSource: LocationDataSource): super(dataSource) {
...
}
It's better to use constructor injection than field injection, and using constructor injection, you have to pass the constructor parameters through the subclasses -- you can't do it only in the base class.