您如何根据使用 Hilt 实例化的 class 注入特定的子 class?

How do you inject a specific subclass based on the which class is instantiated with Hilt?

我有这些存储库依赖于数据源。

class LocationRepository: Repository<String>(LocationDataSource())
class ItemRepository: Repository<String>(ItemDataSource())

我想像这样用 Hilt 注入存储库 class 以防止代码重复。

abstract class Repository<T> {

    @Inject lateinit var dataSource: DataSource<T>
    ...
}

我试过了,但不确定如何让 Hilt 使用正确的。

@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()
    }
    
}

如果您想要避免在每个存储库子class中包含数据源字段,您可以将数据源类型参数和 val 添加到存储库:

class Repository<ValueT, DataSourceT>(val dataSource: DataSourceT) {
  ...
}

class LocationRepository: Repository<Location, LocationDataSource> @Inject constructor(dataSource: LocationDataSource): super(dataSource) {
  ...
}

使用构造函数注入比字段注入更好,并且使用构造函数注入,你必须通过子classes传递构造函数参数——你不能只在基class.