我正在尝试使用新的协程流,我的目标是创建一个简单的存储库,可以从 Web API 获取数据并将其保存到数据库中,同时从数据库返回一个流。
我正在使用 Room 和 Firebase 作为 Web API,现在一切似乎都很简单,直到我尝试将来自 API 的错误传递给 UI。
由于我从数据库获取的流仅包含数据而没有状态,因此,将其与 Web API 结果组合以赋予其状态(例如加载,内容,错误)的正确方法是什么?
我编写的一些代码:
DAO:
@Query("SELECT * FROM users")
fun getUsers(): Flow<List<UserPojo>>
代码仓库:
val users: Flow<List<UserPojo>> = userDao.getUsers()
API调用:
override fun downloadUsers(filters: UserListFilters, onResult: (result: FailableWrapper<MutableList<UserApiPojo>>) -> Unit) {
val data = Gson().toJson(filters)
functions.getHttpsCallable("users").call(data).addOnSuccessListener {
try {
val type = object : TypeToken<List<UserApiPojo>>() {}.type
val users = Gson().fromJson<List<UserApiPojo>>(it.data.toString(), type)
onResult.invoke(FailableWrapper(users.toMutableList(), null))
} catch (e: java.lang.Exception) {
onResult.invoke(FailableWrapper(null, "Error parsing data"))
}
}.addOnFailureListener {
onResult(FailableWrapper(null, it.localizedMessage))
}
}
我希望问题已经足够清晰明了,非常感谢你的帮助。
编辑:由于问题不是很清楚,我将尝试澄清。我的问题是,默认情况下,Room发出的数据流只包含数据,因此如果我订阅该数据流,我只会收到数据(例如,在本例中,我只会收到用户列表)。我的需要是实现一种通知应用状态(例如加载或错误)的方法。目前,我唯一能想到的方法是使用包含状态的“响应”对象,但似乎无法找到实现它的方法。
类似于:
fun getUsers(): Flow<Lce<List<UserPojo>>>{
emit(Loading())
downloadFromApi()
if(downloadSuccessful)
return flowFromDatabase
else
emit(Error(throwable))
}
但是我遇到的明显问题是,来自数据库的流的类型为
Flow<List<UserPojo>>
,我不知道如何通过状态编辑流"丰富它",而不失去对数据库的订阅,并且在每次更新数据库时不需要运行新的网络调用(通过进行map转换)。希望现在更清楚了。
Flow.first() = take(1)
,而对于连接操作,Flow.concat(other) = flowOf(this, other).flattenConcat()
。 - Marko Topolnik