有没有更好的方法在android中使用rxjava实现单一真理源



在我的应用程序中,我有一个使用Room的数据库和一个使用改造的网络服务。我有一个要求,如果本地数据库中没有数据,我需要查询网络并显示进度条。如果网络返回空数据,那么我需要显示一个空视图。其中一个问题是,我需要忽略房间中的空数据,而只考虑服务器上的空数据。这样,当用户没有任何数据时,他只会看到一个加载视图,而在服务器返回空数据后,他会看到空视图。

我已经使用发布主题实现了这一点。Lce(加载内容错误(是数据的包装对象。

val recentPublish = PublishSubject.create<Lce<List<RecentMessage>>>()
fun loadRecentMessages() {
loadMessageFromDB()
loadRecentMessageFromServer()
}
private fun loadMessageFromDB() {
disposable = recentMessageDao.getRecentMessages() // this is a flowable
.subscribeOn(Schedulers.io())
.subscribe({
Timber.d("recent message from db size ${it.size}")
handleMessageFromDB(it)
}, {
it.printStackTrace()
Timber.e("error on flowable from db!")
})
}
protected fun handleMessageFromDB(messages: List<RecentMessage>) {
// only publish if the data is not empty
if (messages.isNotEmpty()) {
recentPublish.onNext(Lce.Content(messages))
}
}
private fun loadRecentMessageFromServer() {
recentPublish.onNext(Lce.Loading())
networkService.getLatestMessage() // this is a single
.subscribe({
val parsedMessages =
DtoConverter.convertRecentPrivateMessageResponse(it, user.id!!)
handleMessageFromServer(parsedMessages)
}, {
it.printStackTrace()
recentPublish.onNext(Lce.Error(it))
Timber.w("failed to load recent message for private chat from server")
})
}
private fun handleMessageFromServer(recentMessages: List<RecentMessage>) {
Timber.i("recent messages from server ${recentMessages.size}")
if (recentMessages.isEmpty()) {
recentPublish.onNext(Lce.Content(arrayListOf()))
} else {
recentMessageDao.saveAll(recentMessages)
}
}

在上面的代码中,我只传递来自服务器的空数据,而忽略来自房间的空数据。这个解决方案有效,但我想知道是否有更好的功能方法来解决这个问题。我是Rxjava的初学者,任何帮助都将不胜感激。非常感谢。

经过一些研究和@EpicPandaForce的评论,我提出了这种方法。我学到了很多关于如何正确使用rxjava的东西,它对我很有帮助。这是我的方法,任何评论都将不胜感激。

fun getMessages(): Observable<Lce<List<RecentMessage>>> {
return Observable.mergeDelayError(getMessagesFromDB(), getMessagesFromNetwork()) // even if network fails, we still want to observe the DB
}
private fun getMessagesFromDB(): Observable<Lce.Content<List<RecentMessage>>> {
return recentMessageDao.getRecentMessages()
.filter {
it.isNotEmpty() // only forward the data from db if it's not empty
}.map {
Lce.Content(it)
}
}
private fun getMessagesFromNetwork(): Observable<Lce<List<RecentMessage>>> {
// first show a loading , then request for data
return Observable.concat(Observable.just(Lce.Loading()), profileService.getLatestMessage()
.flatMap {
processServerResponse(it) // store the data to db
}.onErrorReturn {
Lce.Error(it)
}.filter {
(it as Lce.Content).packet.isEmpty() // only forward data if it's empty
})
}

private fun processServerResponse(response: RecentMessageResponse): Observable<Lce<List<RecentMessage>>> {
return Observable.create {
val parsedMessages =
DtoConverter.convertRecentPrivateMessageResponse(response, user.id!!)
handleMessageFromServer(parsedMessages)
it.onComplete() // we use single source of truth so don't return anyting
}
}

最新更新