Я новичок в Dagger и имею следующую настройку:
// data models
open class BaseEntity (open val id: Long)
data class UserEntity (override val id: Long, val name: String) : BaseEntity(id)
data class FruitEntity (override val id: Long, val status: String) : BaseEntity(id)
// interface to spec common API response operations
interface Repo<T> {
fun getEntities(): List<T>
}
// entity specific implementation of the repo interface
class RepoImpl<T: BaseEntity> @Inject constructor(apiService: ApiService) : Repo<T> {
override fun getEntities(): List<T> {
val entities = apiService.getEntities(...)// get result from respective entity network service, e.g users, fruits etc
return entities
}
}
// DI: provide entity-specific implementations of the interface
@Singleton
@Provides
fun provideUserRepoImpl(userService: UserApiService): RepoImpl<BaseEntity> {
return RepoImpl(userService)
}
@Singleton
@Provides
fun provideFruitRepoImpl(fruitService: FruitApiService): RepoImpl<BaseEntity> {
return RepoImpl(fruitService)
}
Когда я собираю проект, появляется эта ошибка:
error: RepoImpl<com.example.data.model.BaseEntity> is bound multiple times
...
@org.jetbrains.annotations.NotNull @Provides @Singleton com.example.data.source.remote.RepoImpl<com.example.data.model.BaseEntity> com.example.app.di.AppModule.provideUserRepoImpl()
@org.jetbrains.annotations.NotNull @Provides @Singleton com.example.data.source.remote.RepoImpl<com.example.data.model.BaseEntity> com.example.app.di.AppModule.provideFruitRepoImpl()
И когда я пытаюсь предоставить экземпляры, специфичные для сущности, например:
@Singleton
@Provides
fun provideUserRepoImpl(userService: UserApiService): RepoImpl<UserEntity> {
return RepoImpl(userService)
}
@Singleton
@Provides
fun provideFruitRepoImpl(fruitService: FruitApiService): RepoImpl<FruitEntity> {
return RepoImpl(fruitService)
}
Я получаю следующее:
error: RepoImpl<com.example.data.model.BaseEntity> cannot be provided without an @Inject constructor or from an @Provides-annotated method
Также я попытался разделить методы провайдера фруктов и пользователей на их соответствующие модули, но также появляется последняя ошибка, возможно, я неправильно подключаю FruitModule, UserModule и AppModule. У меня похожие проблемы с реализацией интерфейсов.
Что было бы правильным подходом здесь, или вообще невозможно вводить параметризованные классы с помощью Dagger?
UPDATE
Мне удалось решить проблему зависимости от RepoImpl, явно указав каждый объект для инъекции (последний вариант, где мы предоставляем RepoImpl<UserEntity>
и RepoImpl<FruitEntity>
). Я думаю, что аннотация @Inject на конструкторе как-то не регистрировалась,
поэтому пришлось обновить проект.
Однако я пока не могу понять, как обеспечить реализацию (или подтипы) параметризованных интерфейсов.
Рассмотрим, например, параметр ApiService в RepoImpl, определенный следующим образом:
// base service for all types of items
interface ApiService<T: BaseAttributes> {
fun getEntities(): T
}
// service impl for fruits
class FruitService : ApiService<FruitAttributes> {
override fun getEntities(): FruitResponses {...}
}
// service impl for users
class UserService : ApiService<UserAttributes> {
override fun getEntities(): UserResponses {...}
}
// AppModule.kt:
@Singleton
@Provides
fun provideUserService() : ApiService<UserAttributes> {
return UserService()
}
@Singleton
@Provides
fun provideFruitService() : ApiService<FruitAttributes> {
return FruitService()
}
ошибка: "... ApiService<BaseAttributes> cannot be provided without an @Provides-annotated method ..."
тогда * * одна тысяча тридцать одна
...
fun provideUserService() : ApiService<BaseAttributes> {
return UserService() as ApiService<BaseAttributes>
}
...
fun provideFruitService() : ApiService<FruitAttributes> {
return FruitService() as ApiService<BaseAttributes>
}
ошибка: "... ApiService<BaseAttributes> is bound multiple times: ..."
Как еще можно внедрить эти реализации интерфейса?