android - 处理用户输入和网络的反应式流模式
问题描述
我正在使用 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(...)
出现网络错误时会出现问题 - 我的整个订阅都被取消了。似乎我有一些选项来管理故障,但它们看起来都不是很干净:
- 在文本输入完成后有一个内部 observable 发出网络请求
- 使用
onErrorResumeNext
并传递一个哨兵值
这显然不是详尽无遗的,但是在保留来自搜索栏的用户输入流(以及因此有用性)的同时优雅地处理网络错误的适当模式是什么?
解决方案
如果您查看提供单向数据流(例如 MVI)的反应模式,使用诸如 onErrorReturn 之类的运算符是一种非常标准的方法。
按照这样的模式,您通常会将网络调用的状态映射到表示调用状态的对象中。
一个没有任何 MVx 模式的简单示例如下所示,其中来自 RXBinding 的 observable 调用了对 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 模式的精彩文章。
推荐阅读
- python - AWS SNS 记录是否始终是单个元素列表?
- c - 格式说明符 int * 警告信息
- javascript - 选择自动完成ui Jquery后加载数据
- javascript - 在继续引导文件输入中的文件预删除事件之前等待 Sweetalert2 异步确认
- mysql - Microsoft.EntityFrameworkCore 2.1-rc 与 MySql.Data.EntityFrameworkCore
- c - 快速排序中的无限循环
- java - {http://xml.apache.org/axis/}stackTrace:java.net.UnknownHostException: 代理
- jquery - 在 JQuery 数据表中的嵌套 json 对象中呈现列值
- ios - iOS 如何从另一个 View Controller Swift 调用 func
- c# - 将 SolidColorBrush 的颜色绑定到 Button 的背景颜色