Hilt 注入子 class 作为父类型
Hilt injecting child class as parent type
我有 3 个存储库:
interface MainRepository {
...
}
interface LocalRepository {
...
}
interface WebRepository {
...
}
每个存储库都有自己的实现:
@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 {
...
}
如您所见,MainRepository
需要将其他两个存储库都注入其中,但是,我真的不知道该怎么做。
当然我可以用 LocalRepositoryImpl
或 WebRepositoryImpl
类型注入它,但我想用 LocalRepository
或 WebRepository
类型注入它以获得更通用的方法。
这是我尝试编写的模块:
@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)
}
}
我的 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()
}
我的WebData模块:
@InstallIn(ApplicationComponent::class)
@Module
object RemoteDataSourceModule {
@Singleton
@Provides
fun providePopularMovieApi(): PopularMovieApi = PopularMovieApi.getInstance()
}
如何在维护接口类型(LocalRepository
& `WebRepository)的同时正确注入我拥有的实现(LocalRepositoryImpl
& WebRepositoryImpl
)??
您的存储库
interface MainRepository {
...
}
interface LocalRepository {
...
}
interface WebRepository {
...
}
实施(这里没有@Inject 或@Singleton!)
class MainRepositoryImpl constructor(
private val localRepository: LocalRepository,
private val webRepository: WebRepository
) : MainRepository {
...
}
class LocalRepositoryImpl constructor(
private val localMapper: LocalMapper
private val popularMovieDao: PopularMovieDao
) : LocalRepository {
...
}
class WebRepositoryImpl constructor(
private val webMapper: WebMapper,
private val popularMovieApi: PopularMovieApi
) : WebRepository {
...
}
Di.Module(存储库模块)
@Module
@InstallIn(ApplicationComponent::class)
object RepositoryModule {
@Singleton
@Provides
fun provideMainRepository(
localRepository: LocalRepository,
webRepository: WebRepository
): MainRepository = MainRepositoryImpl(localRepository, webRepository)
@Singleton
@Provides
fun provideLocalRepository(
localMapper: LocalMapper,
popularMovieDao: PopularMovieDao
): LocalRepository = LocalRepositoryImpl(localMapper, popularMovieDao)
@Singleton
@Provides
fun provideWebRepository(
webMapper: WebMapper,
popularMovieApi: PopularMovieApi
): WebRepository = WebRepositoryImpl(webMapper, popularMovieApi)
试试这个,告诉我它是否有效。由于您已经为所有存储库提供了 @Provides
,Dagger-Hilt 知道如何创建它们。您是否将 Room
用于 localDatabase?如果是,那么像您那样创建数据库可能是不正确的。如果您没有使用 Room
,您应该开始使用,因为它会让您的生活更轻松。
以下是使用匕首柄创建房间数据库的正确方法:
实体模块
@Entity(tableName = "exampleTableName")
data class ExampleEntity(
@PrimaryKey(autoGenerate = true)
val id: Int,
// ... whatever you need
val header: String = "",
val title: String = "",
val description: String = "",
)
示例数据库
@Database(entities = [ExampleEntity::class], version = 1)
abstract class ExampleDatabase : RoomDatabase() {
abstract fun exampleDao(): ExampleDao
companion object {
const val DATABASE_NAME = "example_db"
}
}
DAO
@Dao
interface DocumentDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(exampleEntity: List<ExampleEntity>)
@Query("SELECT * FROM exampleTableName")
suspend fun getList(): List<ExampleEntity>
}
房间Di.Module
@Module
@InstallIn(ApplicationComponent::class)
object RoomModule {
@Singleton
@Provides
fun provideExampleDB(@ApplicationContext context: Context): ExampleDatabase = Room.databaseBuilder(
context,
ExampleDatabase::class.java,
ExampleDatabase.DATABASE_NAME,
).fallbackToDestructiveMigration().build()
@Singleton
@Provides
fun provideExampleDAO(exampleDatabase: ExampleDatabase): ExampleDao = exampleDatabase.exampleDao()
}
使用@Binds
。而不是你的 object Module
使用以下模块:
@InstallIn(ApplicationComponent::class)
@Module
interface Module {
@Binds
fun bindWebRepository(repository: WebRepositoryImpl): WebRepository
@Binds
fun bindLocalRepository(repository: LocalRepositoryImpl): LocalRepository
}
它告诉 Dagger,如果你需要 WebRepository
依赖,那么它必须提供 WebRepositoryImpl
并且 LocalRepository
和 LocalRepositoryImpl
也是如此。
我有 3 个存储库:
interface MainRepository {
...
}
interface LocalRepository {
...
}
interface WebRepository {
...
}
每个存储库都有自己的实现:
@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 {
...
}
如您所见,MainRepository
需要将其他两个存储库都注入其中,但是,我真的不知道该怎么做。
当然我可以用 LocalRepositoryImpl
或 WebRepositoryImpl
类型注入它,但我想用 LocalRepository
或 WebRepository
类型注入它以获得更通用的方法。
这是我尝试编写的模块:
@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)
}
}
我的 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()
}
我的WebData模块:
@InstallIn(ApplicationComponent::class)
@Module
object RemoteDataSourceModule {
@Singleton
@Provides
fun providePopularMovieApi(): PopularMovieApi = PopularMovieApi.getInstance()
}
如何在维护接口类型(LocalRepository
& `WebRepository)的同时正确注入我拥有的实现(LocalRepositoryImpl
& WebRepositoryImpl
)??
您的存储库
interface MainRepository {
...
}
interface LocalRepository {
...
}
interface WebRepository {
...
}
实施(这里没有@Inject 或@Singleton!)
class MainRepositoryImpl constructor(
private val localRepository: LocalRepository,
private val webRepository: WebRepository
) : MainRepository {
...
}
class LocalRepositoryImpl constructor(
private val localMapper: LocalMapper
private val popularMovieDao: PopularMovieDao
) : LocalRepository {
...
}
class WebRepositoryImpl constructor(
private val webMapper: WebMapper,
private val popularMovieApi: PopularMovieApi
) : WebRepository {
...
}
Di.Module(存储库模块)
@Module
@InstallIn(ApplicationComponent::class)
object RepositoryModule {
@Singleton
@Provides
fun provideMainRepository(
localRepository: LocalRepository,
webRepository: WebRepository
): MainRepository = MainRepositoryImpl(localRepository, webRepository)
@Singleton
@Provides
fun provideLocalRepository(
localMapper: LocalMapper,
popularMovieDao: PopularMovieDao
): LocalRepository = LocalRepositoryImpl(localMapper, popularMovieDao)
@Singleton
@Provides
fun provideWebRepository(
webMapper: WebMapper,
popularMovieApi: PopularMovieApi
): WebRepository = WebRepositoryImpl(webMapper, popularMovieApi)
试试这个,告诉我它是否有效。由于您已经为所有存储库提供了 @Provides
,Dagger-Hilt 知道如何创建它们。您是否将 Room
用于 localDatabase?如果是,那么像您那样创建数据库可能是不正确的。如果您没有使用 Room
,您应该开始使用,因为它会让您的生活更轻松。
以下是使用匕首柄创建房间数据库的正确方法:
实体模块
@Entity(tableName = "exampleTableName")
data class ExampleEntity(
@PrimaryKey(autoGenerate = true)
val id: Int,
// ... whatever you need
val header: String = "",
val title: String = "",
val description: String = "",
)
示例数据库
@Database(entities = [ExampleEntity::class], version = 1)
abstract class ExampleDatabase : RoomDatabase() {
abstract fun exampleDao(): ExampleDao
companion object {
const val DATABASE_NAME = "example_db"
}
}
DAO
@Dao
interface DocumentDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(exampleEntity: List<ExampleEntity>)
@Query("SELECT * FROM exampleTableName")
suspend fun getList(): List<ExampleEntity>
}
房间Di.Module
@Module
@InstallIn(ApplicationComponent::class)
object RoomModule {
@Singleton
@Provides
fun provideExampleDB(@ApplicationContext context: Context): ExampleDatabase = Room.databaseBuilder(
context,
ExampleDatabase::class.java,
ExampleDatabase.DATABASE_NAME,
).fallbackToDestructiveMigration().build()
@Singleton
@Provides
fun provideExampleDAO(exampleDatabase: ExampleDatabase): ExampleDao = exampleDatabase.exampleDao()
}
使用@Binds
。而不是你的 object Module
使用以下模块:
@InstallIn(ApplicationComponent::class)
@Module
interface Module {
@Binds
fun bindWebRepository(repository: WebRepositoryImpl): WebRepository
@Binds
fun bindLocalRepository(repository: LocalRepositoryImpl): LocalRepository
}
它告诉 Dagger,如果你需要 WebRepository
依赖,那么它必须提供 WebRepositoryImpl
并且 LocalRepository
和 LocalRepositoryImpl
也是如此。