Koin Dependency Injection 在本地和远程数据源之间切换
Koin Dependency Injection switching between local and remote data source
所以我正在用远程数据源编写这个应用程序。我想添加本地数据库存储功能。我已经设置了一个架构,我有一个接口 DataSource
。 RemoteDataSource
和 LocalDataSource
class 实现了该接口。 RemoteDataSource
注入了 ApiInterface
改造,LocalDataSource
注入了 DAO。
现在有了这个存储库接口和实现 SomeDataRepository
和 SomeDataRepositoryImpl
。如果我希望存储库能够从 api 获取数据并将其保存到数据库,我该怎么做?
目前我已经将 RemoteDataSource
和 LocalDataSource
class 都注入到 SomeDataRepositoryImpl
中以访问来自不同数据源的方法。这样我就可以调用 localDataSource.saveToDb()
and/or remoteDatSource.fetchSomeData()
int SomeRepositoryImpl
class 之类的东西。但我不知道将具体实现传递给 class 是否可行。
但是如果我将单个 DataSource
接口传递给 SomeDataRepository
,我将不得不在接口 DataSource
中定义一个 saveToDb()
函数,然后我也必须在 RemoteDataSource
中实施,这不是很好。
任何人都可以指导我了解此解决方案的最佳方法。
而且,当我在做的时候,在 api 接口中用 LiveData
包装器 class 包装数据以进行改造有什么好处吗?因为我不认为当在存储库上调用方法时,我想在存储库中观察它,然后访问数据以将其放入本地数据库。
由于您希望本地数据源充当远程数据源的回退,您可以根据需要创建另一个数据源实现,该实现是 composition of the local and remote data sources. This composite data source can contain the fallback logic and handle the delegation 到远程和本地数据源。一旦你这样做了,创建一个Koin模块来构建这些,并将复合数据源绑定到数据源接口是一件简单的事情。
假设这是您的界面和您已有的两个数据源:
interface DataSource {
fun getData(): Data
}
class RemoteDataSource : DataSource {
// ...
}
class LocalDataSource : DataSource {
// ...
}
然后你可以像这样创建第三个实现:
class CompositeDataSource(
val remote: RemoteDataSource,
val local: LocalDataSource
) : DataSource {
override fun getData() : Data {
return try {
remote.getData()
} catch (e: Exception) {
local.getData()
}
}
}
要定义所有这些,您的 koin 模块将如下所示
module {
single { RemoteDataSource() }
single { LocalDataSource() }
single<DataSource> { CompositeDataSource(remote = get(), local = get()) }
}
编辑:如果你真正想要的是一个缓存,你可以像这样使用本地数据源作为你的缓存:
class CompositeDataSource(
val remote: RemoteDataSource,
val local: LocalDataSource
) : DataSource {
override fun getData() : Data {
return try {
remote.getData().also { local.saveData(it) }
} catch (e: Exception) {
local.getData()
}
}
}
您可以尝试下一个方法,它只需很少的改动并且对我有用:
添加远程和本地数据源接口,应继承DataSource主接口
interface QuotesDataSource {
fun getQuotes(skip: Int = 0, force: Boolean = false): Flow<List<Quote>>
suspend fun updateQuotes(quotes: List<Quote>)
}
interface QuotesRemoteDataSource : QuotesDataSource
interface QuotesLocalDataSource : QuotesDataSource
然后使用这些接口创建 koin 模块
val repoModule = module {
single { QuotesApi() }
single<QuotesLocalDataSource> { QuotesDatabase(get()) }
single<QuotesRemoteDataSource> { QuotesRemote(get()) }
single<QuotesDataSource> {
QuotesRepository(
local = get<QuotesLocalDataSource>(),
remote = get<QuotesRemoteDataSource>()
)
}
}
所以我正在用远程数据源编写这个应用程序。我想添加本地数据库存储功能。我已经设置了一个架构,我有一个接口 DataSource
。 RemoteDataSource
和 LocalDataSource
class 实现了该接口。 RemoteDataSource
注入了 ApiInterface
改造,LocalDataSource
注入了 DAO。
现在有了这个存储库接口和实现 SomeDataRepository
和 SomeDataRepositoryImpl
。如果我希望存储库能够从 api 获取数据并将其保存到数据库,我该怎么做?
目前我已经将 RemoteDataSource
和 LocalDataSource
class 都注入到 SomeDataRepositoryImpl
中以访问来自不同数据源的方法。这样我就可以调用 localDataSource.saveToDb()
and/or remoteDatSource.fetchSomeData()
int SomeRepositoryImpl
class 之类的东西。但我不知道将具体实现传递给 class 是否可行。
但是如果我将单个 DataSource
接口传递给 SomeDataRepository
,我将不得不在接口 DataSource
中定义一个 saveToDb()
函数,然后我也必须在 RemoteDataSource
中实施,这不是很好。
任何人都可以指导我了解此解决方案的最佳方法。
而且,当我在做的时候,在 api 接口中用 LiveData
包装器 class 包装数据以进行改造有什么好处吗?因为我不认为当在存储库上调用方法时,我想在存储库中观察它,然后访问数据以将其放入本地数据库。
由于您希望本地数据源充当远程数据源的回退,您可以根据需要创建另一个数据源实现,该实现是 composition of the local and remote data sources. This composite data source can contain the fallback logic and handle the delegation 到远程和本地数据源。一旦你这样做了,创建一个Koin模块来构建这些,并将复合数据源绑定到数据源接口是一件简单的事情。
假设这是您的界面和您已有的两个数据源:
interface DataSource {
fun getData(): Data
}
class RemoteDataSource : DataSource {
// ...
}
class LocalDataSource : DataSource {
// ...
}
然后你可以像这样创建第三个实现:
class CompositeDataSource(
val remote: RemoteDataSource,
val local: LocalDataSource
) : DataSource {
override fun getData() : Data {
return try {
remote.getData()
} catch (e: Exception) {
local.getData()
}
}
}
要定义所有这些,您的 koin 模块将如下所示
module {
single { RemoteDataSource() }
single { LocalDataSource() }
single<DataSource> { CompositeDataSource(remote = get(), local = get()) }
}
编辑:如果你真正想要的是一个缓存,你可以像这样使用本地数据源作为你的缓存:
class CompositeDataSource(
val remote: RemoteDataSource,
val local: LocalDataSource
) : DataSource {
override fun getData() : Data {
return try {
remote.getData().also { local.saveData(it) }
} catch (e: Exception) {
local.getData()
}
}
}
您可以尝试下一个方法,它只需很少的改动并且对我有用:
添加远程和本地数据源接口,应继承DataSource主接口
interface QuotesDataSource {
fun getQuotes(skip: Int = 0, force: Boolean = false): Flow<List<Quote>>
suspend fun updateQuotes(quotes: List<Quote>)
}
interface QuotesRemoteDataSource : QuotesDataSource
interface QuotesLocalDataSource : QuotesDataSource
然后使用这些接口创建 koin 模块
val repoModule = module {
single { QuotesApi() }
single<QuotesLocalDataSource> { QuotesDatabase(get()) }
single<QuotesRemoteDataSource> { QuotesRemote(get()) }
single<QuotesDataSource> {
QuotesRepository(
local = get<QuotesLocalDataSource>(),
remote = get<QuotesRemoteDataSource>()
)
}
}