使用来自不同数据源(网络和房间)的存储库模式将数据列表返回给 viewModel
returning a list of data to viewModel using Repository pattern from different data sources (network and room)
我正在使用带存储库模式的 MVVM 开发 Kotlin 应用程序。
我有一个显示小行星列表的主要片段。
这是我想要实现的流程。
- 当用户打开主片段时,我会检查本地数据库(房间)中是否存储有小行星数据。
- 如果是我会显示存储的数据
- 如果没有,我会调用 API 获取小行星,然后我会将数据从 API 存储到本地数据库
所以根据我对存储库模式的理解,viewModel 不应该关心数据源是来自 API 还是本地数据库。
所以我在 viewModel 将调用的存储库中定义了这个函数
override suspend fun getAsteroid(): List<Asteroid> {
var result : List<Asteroid>
try {
var isDataAvailable = getAnyAsteroidFromDb()
if (isDataAvailable == null) {
result = getAsteroidApi().asDomainModel()
} else {
result = getAsteroidFromDb()
}
} catch (e : Exception) {
}
return result
}
getAnyAsteroidFromDb
检查房间内的数据可用性
getAsteroidApi
从网络调用中获取数据
getAsteroidFromDb
从房间
获取数据
问题是 getAsteroidFromDb
returns 来自 Dao 的 Livedata
@Query("SELECT * FROM asteroid_tbl")
fun getAsteroidsFromDb () : LiveData<List<AsteroidEntity>>
以及函数本身 getAsteroid
returns 小行星列表。
假设我将 return 类型更改为 Livedata ,这将导致另一个问题,因为 api 不是 return Livedata。
我有点卡在这里,我想我做错了什么,或者我对 MVVM 和库模式的低估仍然不够好。
任何想法或想法将不胜感激!
您应该能够return LiveData 值:
override suspend fun getAsteroid(): List<Asteroid> {
var result : List<Asteroid>
try {
var isDataAvailable = getAnyAsteroidFromDb()
if (isDataAvailable == null) {
result = getAsteroidApi().asDomainModel()
} else {
result = getAsteroidFromDb().value //<==List<Asteroid>
}
} catch (e : Exception) {
}
return result
}
对此有多种解决方案,但由于您使用的是 MVVM 模式。因此,我想向您推荐一种适用于这种情况的模式。
每当出现必须检查我们的本地数据库或调用我们的后端的情况时 API。通常的调用结构是只有一点数据源,避免歧义等问题。
因此,虽然您可以轻松地从 LiveData 获取 value
或将 API 响应转换为 LiveData
。我建议你的结构如下。
- 检查本地数据库中的数据。
- 如果本地数据库中有数据,请获取它。
- 如果本地数据库中没有数据,调用API,获取结果,将其存储在本地数据库中。
- 在 API 结果成功后,您可以再次查询本地数据库并获得结果。
这确保您的单一事实来源仍然是您的数据库,并且您可以轻松地进行调用。
如果您不想 return 存储库中的实时数据,您可以解包从 Room 获取的实时数据并使用其中的值。那应该给你小行星对象的列表。所以,使用这样的东西:
override suspend fun getAsteroid(): List<Asteroid> {
var result : List<Asteroid>
try {
var isDataAvailable = getAnyAsteroidFromDb()
if (isDataAvailable == null) {
result = getAsteroidApi().asDomainModel()
} else {
val data = getAsteroidFromDb()
result = data.value
}
} catch (e : Exception) {
}
return result
}
我正在使用带存储库模式的 MVVM 开发 Kotlin 应用程序。
我有一个显示小行星列表的主要片段。
这是我想要实现的流程。
- 当用户打开主片段时,我会检查本地数据库(房间)中是否存储有小行星数据。
- 如果是我会显示存储的数据
- 如果没有,我会调用 API 获取小行星,然后我会将数据从 API 存储到本地数据库
所以根据我对存储库模式的理解,viewModel 不应该关心数据源是来自 API 还是本地数据库。
所以我在 viewModel 将调用的存储库中定义了这个函数
override suspend fun getAsteroid(): List<Asteroid> {
var result : List<Asteroid>
try {
var isDataAvailable = getAnyAsteroidFromDb()
if (isDataAvailable == null) {
result = getAsteroidApi().asDomainModel()
} else {
result = getAsteroidFromDb()
}
} catch (e : Exception) {
}
return result
}
getAnyAsteroidFromDb
检查房间内的数据可用性
getAsteroidApi
从网络调用中获取数据
getAsteroidFromDb
从房间
问题是 getAsteroidFromDb
returns 来自 Dao 的 Livedata
@Query("SELECT * FROM asteroid_tbl")
fun getAsteroidsFromDb () : LiveData<List<AsteroidEntity>>
以及函数本身 getAsteroid
returns 小行星列表。
假设我将 return 类型更改为 Livedata ,这将导致另一个问题,因为 api 不是 return Livedata。
我有点卡在这里,我想我做错了什么,或者我对 MVVM 和库模式的低估仍然不够好。
任何想法或想法将不胜感激!
您应该能够return LiveData 值:
override suspend fun getAsteroid(): List<Asteroid> {
var result : List<Asteroid>
try {
var isDataAvailable = getAnyAsteroidFromDb()
if (isDataAvailable == null) {
result = getAsteroidApi().asDomainModel()
} else {
result = getAsteroidFromDb().value //<==List<Asteroid>
}
} catch (e : Exception) {
}
return result
}
对此有多种解决方案,但由于您使用的是 MVVM 模式。因此,我想向您推荐一种适用于这种情况的模式。
每当出现必须检查我们的本地数据库或调用我们的后端的情况时 API。通常的调用结构是只有一点数据源,避免歧义等问题。
因此,虽然您可以轻松地从 LiveData 获取 value
或将 API 响应转换为 LiveData
。我建议你的结构如下。
- 检查本地数据库中的数据。
- 如果本地数据库中有数据,请获取它。
- 如果本地数据库中没有数据,调用API,获取结果,将其存储在本地数据库中。
- 在 API 结果成功后,您可以再次查询本地数据库并获得结果。
这确保您的单一事实来源仍然是您的数据库,并且您可以轻松地进行调用。
如果您不想 return 存储库中的实时数据,您可以解包从 Room 获取的实时数据并使用其中的值。那应该给你小行星对象的列表。所以,使用这样的东西:
override suspend fun getAsteroid(): List<Asteroid> {
var result : List<Asteroid>
try {
var isDataAvailable = getAnyAsteroidFromDb()
if (isDataAvailable == null) {
result = getAsteroidApi().asDomainModel()
} else {
val data = getAsteroidFromDb()
result = data.value
}
} catch (e : Exception) {
}
return result
}