Kotlin、RxJava2:在用户交互后进行组合和重试
Kotlin, RxJava2: compose and retryWhen after user interaction
在过去的两天里,我阅读了很多关于 rxJava retryWhen 运算符的内容。
, here, here 还有一些我忘记了。
但不幸的是我无法让它工作。
我想要实现的是,我打了一个 API 电话。如果调用 returns 出错,我将向用户显示带有重新加载按钮的 SnackBar。如果用户点击这个按钮,我想重新订阅链。
这是我的代码:
interface RetrofitApi {
@GET("/v1/loadMyData")
fun getMyData(): Single<Response<DataResponse>>
}
其中 Response 来自 retrofit2。我需要它来包装数据 class 以检查响应是否成功。
下一个乐趣是在 ViewModel 的存储库中调用的:
override fun loadMyData(): Observable<Resource<DataResponse>> {
return retrofitApi
.getMyData()
.compose(getRetryTransformer())
.toObservable()
.compose(getResponseTransformer())
}
Resource 是调用状态(成功、错误、加载)的另一个包装器。
最后是变形金刚:
private fun <Data> getRetryTransformer(): SingleTransformer<Response<Data>, Response<Data>> {
return SingleTransformer { singleResponse ->
singleResponse
.onErrorReturn {
singleResponse.blockingGet()
}
.retryWhen { errors ->
errors.zipWith(retrySubject.toFlowable(BackpressureStrategy.LATEST),
BiFunction<Throwable, Boolean, Flowable<Throwable>> { throwable: Throwable, isRetryEnabled: Boolean ->
if (isRetryEnabled) {
Flowable.just(null)
} else {
Flowable.error(throwable)
}
})
}
}
}
重试主题:
private val retrySubject = PublishSubject.create<Boolean>()
当用户点击重试按钮时,我调用:
retrySubject.onNext(true)
现在的问题是,错误没有返回到 ViewModel 并且 SnackBar 从未显示。我也尝试了 onErrorResumeNext() 但没有成功。整个 retryWhen/zipWith 部分似乎有效。因为在存储库中还有一些 API 调用没有重试行为(尚未)并且显示了 SnackBar。这意味着,我在显示 SnackBar 的地方进行了另一个调用 -> 单击按钮,重试转换按预期工作。
如果您需要更多信息,请随时询问!任何帮助表示赞赏!
奇怪,只要你用对了方法,它就会起作用。
我以某种方式阅读了我需要在 doOnError{...} 中设法显示我的 Snackbar。
这是我的工作重试变压器:
private fun <Data> getRetryTransformer(): SingleTransformer<Response<Data>, Response<Data>> {
return SingleTransformer { singleResponse ->
singleResponse
.doOnError {
errorEventSubject.onNext(it)
}
.retryWhen { errors ->
errors.zipWith(retrySubject.toFlowable(BackpressureStrategy.LATEST),
BiFunction<Throwable, Boolean, Flowable<Throwable>> { throwable: Throwable, isRetryEnabled: Boolean ->
if (isRetryEnabled) {
Flowable.just(throwable)
} else {
Flowable.error(throwable)
}
})
}
}
}
链条现在看起来像这样(我觉得很漂亮):
override fun loadMyData(): Observable<Resource<DataResponse>> {
return retrofitApi
.getMyData()
.compose(getRetryTransformer())
.toObservable()
.compose(getResponseTransformer())
}
我还需要将错误传播到我的 ViewModel 是第二个 PublishSubject:
private val errorEventSubject = PublishSubject.create<Throwable>()
在 ViewModel 中,我观察了它的变化并显示了 Snackbar。
而已。
在过去的两天里,我阅读了很多关于 rxJava retryWhen 运算符的内容。
但不幸的是我无法让它工作。 我想要实现的是,我打了一个 API 电话。如果调用 returns 出错,我将向用户显示带有重新加载按钮的 SnackBar。如果用户点击这个按钮,我想重新订阅链。
这是我的代码:
interface RetrofitApi {
@GET("/v1/loadMyData")
fun getMyData(): Single<Response<DataResponse>>
}
其中 Response 来自 retrofit2。我需要它来包装数据 class 以检查响应是否成功。
下一个乐趣是在 ViewModel 的存储库中调用的:
override fun loadMyData(): Observable<Resource<DataResponse>> {
return retrofitApi
.getMyData()
.compose(getRetryTransformer())
.toObservable()
.compose(getResponseTransformer())
}
Resource 是调用状态(成功、错误、加载)的另一个包装器。
最后是变形金刚:
private fun <Data> getRetryTransformer(): SingleTransformer<Response<Data>, Response<Data>> {
return SingleTransformer { singleResponse ->
singleResponse
.onErrorReturn {
singleResponse.blockingGet()
}
.retryWhen { errors ->
errors.zipWith(retrySubject.toFlowable(BackpressureStrategy.LATEST),
BiFunction<Throwable, Boolean, Flowable<Throwable>> { throwable: Throwable, isRetryEnabled: Boolean ->
if (isRetryEnabled) {
Flowable.just(null)
} else {
Flowable.error(throwable)
}
})
}
}
}
重试主题:
private val retrySubject = PublishSubject.create<Boolean>()
当用户点击重试按钮时,我调用:
retrySubject.onNext(true)
现在的问题是,错误没有返回到 ViewModel 并且 SnackBar 从未显示。我也尝试了 onErrorResumeNext() 但没有成功。整个 retryWhen/zipWith 部分似乎有效。因为在存储库中还有一些 API 调用没有重试行为(尚未)并且显示了 SnackBar。这意味着,我在显示 SnackBar 的地方进行了另一个调用 -> 单击按钮,重试转换按预期工作。
如果您需要更多信息,请随时询问!任何帮助表示赞赏!
奇怪,只要你用对了方法,它就会起作用。 我以某种方式阅读了我需要在 doOnError{...} 中设法显示我的 Snackbar。
这是我的工作重试变压器:
private fun <Data> getRetryTransformer(): SingleTransformer<Response<Data>, Response<Data>> {
return SingleTransformer { singleResponse ->
singleResponse
.doOnError {
errorEventSubject.onNext(it)
}
.retryWhen { errors ->
errors.zipWith(retrySubject.toFlowable(BackpressureStrategy.LATEST),
BiFunction<Throwable, Boolean, Flowable<Throwable>> { throwable: Throwable, isRetryEnabled: Boolean ->
if (isRetryEnabled) {
Flowable.just(throwable)
} else {
Flowable.error(throwable)
}
})
}
}
}
链条现在看起来像这样(我觉得很漂亮):
override fun loadMyData(): Observable<Resource<DataResponse>> {
return retrofitApi
.getMyData()
.compose(getRetryTransformer())
.toObservable()
.compose(getResponseTransformer())
}
我还需要将错误传播到我的 ViewModel 是第二个 PublishSubject:
private val errorEventSubject = PublishSubject.create<Throwable>()
在 ViewModel 中,我观察了它的变化并显示了 Snackbar。 而已。