gpt4 book ai didi

android - Dagger:如何提供参数化基类型的具体实现?

转载 作者:行者123 更新时间:2023-11-29 01:02:01 24 4
gpt4 key购买 nike

我是 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

我也曾尝试将 fruits 和 users 的提供者方法分离到各自的模块中,但后一个错误也出现了,也许我没有正确连接 FruitModule、UserModule 和 AppModule。我在提供接口(interface)实现时遇到了类似的问题。

这里什么是正确的方法,或者根本不可能用 Dagger 注入(inject)参数化类?

更新

我通过显式提供每个要注入(inject)的对象(我们提供 RepoImpl<UserEntity>RepoImpl<FruitEntity> 的后一个选项)设法解决了 RepoImpl 上的依赖性问题。我认为构造函数上的 @Inject 注释不知何故没有被注册,所以不得不刷新项目。

但是,我还不知道如何提供参数化接口(interface)的实现(或子类型)。例如,考虑 RepoImpl 的 ApiService 参数定义如下:

// 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: ..."

我还能如何注入(inject)接口(interface)的这些实现?

最佳答案

原来有一个 well-discussed wildcard issue在 Dagger / Kotlin 泛型上。特别是,参数化类上的“如果没有@Provides-annotated 方法就无法提供”错误需要在注入(inject)站点使用@JvmSuppressWildcard 注释抑制通配符类型(协变或逆变)的生成。所以我会这样做:

class RepoImpl<T: BaseEntity> @Inject constructor(apiService: @kotlin.jvm.JvmSuppressWildcards ApiService) : Repo<T> { ... }

尽管我实际上最终将 RepoImpl 转换为抽象类并为 Fruit 和 User 类型创建了具体类,并改为在模块级别提供它们:

class UserRepoImpl @Inject constructor(apiService: UserService) : RemoteRepoImpl(apiService) 
class FruitRepoImpl @Inject constructor(apiService: FruitService) : RemoteRepoImpl(apiService)

related SO question包含另一个示例。

最后,这个Kotlin+Dagger线程包含一些与此问题相关的不错的陷阱和提示

关于android - Dagger:如何提供参数化基类型的具体实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50390274/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com