我正在使用RxKotlin构建我最新的Android应用程序,但遇到一个熟悉的问题:如何以类似Rx的方式处理网络错误。
我有一个针对TextView
的搜索字词流,如下所示:
searchBar
.queryTextObservable()
.debounce(500, TimeUnit.MILLISECONDS)
.map { it.trim() }
.filter { it.isNotBlank() }
.observeOn(Schedulers.io())
这是侦听文本输入更改的一种有用方法,因此,我随后扩展代码以将准备好的文本馈送到网络请求中(使用带有RxJava扩展名的Retrofit库)以搜索:
searchBar
.queryTextObservable()
.debounce(500, TimeUnit.MILLISECONDS)
.map { it.trim() }
.filter { it.isNotBlank() }
.observeOn(Schedulers.io())
.switchMap { search(it) }
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(...)
出现网络错误时会发生问题-我的整个订阅都被取消了。似乎我有一些方法可以管理故障,但是似乎没有一个很干净:
onErrorResumeNext
并传递哨兵值这显然不是详尽无遗的,但是什么是合适的模式来适当地处理网络错误,同时保留来自搜索栏的用户输入流(以及有用性)?
答案 0 :(得分:0)
如果您查看提供单向数据流(例如MVI)的反应模式,则使用onErrorReturn这样的运算符是一种非常标准的方法。
按照这些模式,通常将网络呼叫的状态映射到一个代表呼叫状态的对象。
一个没有任何MVx模式的简单示例如下所示,其中从RXBinding观察到的调用了对API的调用,但它不仅返回了API的数据,还返回了一个状态对象,该状态对象随后可以在屏幕。
private val disposables = CompositeDisposable()
override fun onStart() {
super.onStart()
disposables.add(
RxView.clicks(load_data_button)
.flatMap { requestData() }
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::renderRequestState)
)
}
override fun onStop() {
disposables.clear()
super.onStop()
}
private fun requestData(): Observable<RequestState> {
return myApi.requestData()
.toObservable()
.subscribeOn(Schedulers.io())
.map<RequestState>(RequestState::Success)
.onErrorReturn(RequestState::Error)
.startWith(RequestState.InFlight)
}
private fun renderRequestState(requestState: RequestState) {
when (requestState) {
RequestState.InFlight -> showProgress()
is RequestState.Success -> showResult(requestState.result)
is RequestState.Error -> showError(requestState.error)
}
}
sealed class RequestState {
object InFlight : RequestState()
data class Success(val result: MyData) : RequestState()
data class Error(val error: Throwable) : RequestState()
}
Hannes Dorfmann用这种方法写了很多有关MVI模式的文章。