有没有更好的方法在android中用rxjava实现单一真相来源
在我的应用程序中,我有使用房间的数据库和使用翻新的网络服务。我有一个要求,如果本地数据库中没有数据,我需要查询网络并显示进度条。如果网络返回空数据,那么我需要显示一个空视图。其中一个问题是,我需要忽略来自房间的空数据,而只考虑服务器的空数据,这样当用户没有任何数据时,他只看到一个加载视图,在服务器返回空数据后,他将看到空视图。 我已经使用发布主题实现了这一点。Lce(加载内容错误)是数据周围的包装对象有没有更好的方法在android中用rxjava实现单一真相来源,android,rx-java2,Android,Rx Java2,在我的应用程序中,我有使用房间的数据库和使用翻新的网络服务。我有一个要求,如果本地数据库中没有数据,我需要查询网络并显示进度条。如果网络返回空数据,那么我需要显示一个空视图。其中一个问题是,我需要忽略来自房间的空数据,而只考虑服务器的空数据,这样当用户没有任何数据时,他只看到一个加载视图,在服务器返回空数据后,他将看到空视图。 我已经使用发布主题实现了这一点。Lce(加载内容错误)是数据周围的包装对象 val recentPublish = PublishSubject.create<Lc
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)
}
}
val recentPublish=PublishSubject.create()
有趣的loadRecentMessages(){
loadMessageFromDB()
loadRecentMessageFromServer()
}
private fun loadMessageFromDB(){
一次性=recentMessageDao.getRecentMessages()//这是一个可流动的
.subscribeOn(Schedulers.io())
.订阅({
d(“来自db size${it.size}的最新消息”)
handleMessageFromDB(it)
}, {
it.printStackTrace()
Timber.e(“数据库中可流动的错误!”)
})
}
受保护的fun handleMessageFromDB(消息:列表){
//仅在数据不为空时发布
if(messages.isNotEmpty()){
recentPublish.onNext(Lce.Content(messages))
}
}
private fun loadRecentMessageFromServer(){
recentPublish.onNext(Lce.Loading())
networkService.getLatestMessage()//这是一个
.订阅({
val parsedMessages=
DtoConverter.convertRecentPrivateMessageResponse(it,user.id!!)
handleMessageFromServer(解析消息)
}, {
it.printStackTrace()
recentPublish.onNext(Lce.Error(it))
Timber.w(“无法从服务器加载私人聊天的最新消息”)
})
}
private fun handleMessageFromServer(最近消息:列表){
i(“来自服务器${recentMessages.size}的最近消息”)
if(recentMessages.isEmpty()){
recentPublish.onNext(Lce.Content(arrayListOf()))
}否则{
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
}
}
fun getMessages():可观察{
return Observable.mergeDelayError(getMessagesFromDB(),getMessagesFromNetwork())//即使网络出现故障,我们仍然希望观察数据库
}
private fun getMessagesFromDB():可观察{
返回recentMessageDao.getRecentMessages()
.过滤器{
it.isNotEmpty()//仅当数据不为空时才从db转发数据
}.地图{
Lce.内容(it)
}
}
private fun getMessagesFromNetwork():可观察{
//首先显示加载,然后请求数据
返回Observable.concat(Observable.just(Lce.load()),profileService.getLatestMessage()
.平面图{
processServerResponse(it)//将数据存储到数据库
}A.报税表{
Lce.错误(it)
}.过滤器{
(它作为Lce.Content.packet.isEmpty()//仅在数据为空时转发数据
})
}
private fun processServerResponse(响应:RecentMessageResponse):可观察{
返回可观察的。创建{
val parsedMessages=
DtoConverter.convertRecentPrivateMessageResponse(响应,user.id!!)
handleMessageFromServer(解析消息)
it.onComplete()//我们使用单一的真相来源,因此不返回任何消息
}
}
你使用多个独立订阅来进行顺序操作,这会导致竞争条件,考虑使用<代码>平面图{<代码> >运算符。甚至可以<代码>平面图。{
网络请求,然后将该响应+以前的DB数据映射成对
。感谢您的响应@EpicPandaForce,我是rxjava的初学者,所以我很难想出如何做。如果您有时间,请您提供一些代码来帮助我。flatMap
谢谢@我想我已经猜到了。我已经发布了我的答案,我认为它很好。