所以我是RxJava的初学者,但这就是我想要完成的事情:
MainViewModel与存储库进行通信。存储库同时具有LocalDataStore(与数据库通信)和RemoteDataStore(Retrofit)两者都是接口DataStore的不同实现。)
我想要实现的是从Repository调用fetchData,返回一个Observable但是:
但是,我不知道如何实现这个逻辑。订阅发生在ViewModel的末尾,但我无法真正将Observable从Repository end(?)更改为LocalDataStore。将数据上传到数据库中也会返回一个Observable(准确地说是Single),并且要使它工作,它需要订阅。
有人可以向我解释或指出我的方向吗?
我的代码(存储库评论中的问题):
远程数据存储
override fun getData(): Observable<SomeData> = api
.getData(token)
.flatMapIterable { x -> x }
本地数据存储
override fun saveData(data: SomeData): Single<SomeData> {
return database.upsert(data)
}
存储库
fun getData(): Observable<SomeData> {
return
remoteDataStore.getData()
.doOnError {
localDataStore.getData() //? this will invoke but nothing happens because I'm not subscribed to it
}
.doOnNext {
saveData(it) //The same as before, nothing will happen
}
}
视图模型
override fun fetchData() {
repository.getData()
.observeOn(androidScheduler)
.subscribeOn(threadScheduler)
.subscribe(
{ data: SomeData ->
dataList.add(data)
},
{ throwable: Throwable? ->
handleError(throwable)
},
{
//send data to view
},
{ disposable: Disposable ->
compositeDisposable.add(disposable)
}
)
}
感谢您的时间。
答案 0 :(得分:4)
您需要使用onErrorResumeNext方法之一。我还建议将您的流类型从Observable
更改为Single
,因为您的数据的性质似乎是获取数据一次或抛出错误。这只是一个很好的API设计。
在您的特定情况下,我将以这种方式实现存储库:
class RepositoryImpl @Inject constructor(private val localRepository: Repository, private val remoteRepository: Repository) : Repository {
override fun getData(): Single<Data> = remoteRepository.getData()
.onErrorResumeNext { throwable ->
if (throwable is IOException) {
return localRepository.getData()
}
return Single.error(throwable)
}
}
您可能会问为什么只能抓住IOException
?我通常只处理这个例外,不会错过任何关键但只有不重要的网络错误。如果您将捕获可能遗漏的每个例外,例如NullPointerException
。
答案 1 :(得分:1)
onErrorResumeNext
是您正在寻找的。 doOnError
调用副作用操作,不会将原始Observable
替换为另一个。