Kotlin,RxJava2:撰写并重试用户互动后

时间:2019-03-12 12:35:23

标签: kotlin rx-java2 retrywhen

在过去两天里,我读到了很多有关rxJava retryWhen运算符的信息。 Hereherehere,还有一些我忘了。

但不幸的是,我无法使它正常工作。 我想达到的目的是,我进行了API调用。如果调用返回错误,则显示带有重新加载按钮的SnackBar给用户。如果用户单击此按钮,我想重新订阅该链。

这是我的代码:

interface RetrofitApi {

@GET("/v1/loadMyData")
fun getMyData(): Single<Response<DataResponse>>
}

响应来自retrofit2。我需要它包装数据类以检查响应是否成功。

下一个乐趣是从ViewModel的存储库中调用的:

override fun loadMyData(): Observable<Resource<DataResponse>> {
    return retrofitApi
            .getMyData()
            .compose(getRetryTransformer())
            .toObservable()
            .compose(getResponseTransformer())
}

资源是调用状态(SUCCESS,ERROR,LOADING)的另一个包装。

最后是变形金刚:

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)
                                }
                            })
                }
    }
}

retrySubject:

private val retrySubject = PublishSubject.create<Boolean>()

当用户单击“重试”按钮时,我会呼叫:

retrySubject.onNext(true)

现在的问题是,错误没有返回到ViewModel,并且从未显示SnackBar。我也尝试了onErrorResumeNext(),但没有成功。整个retryWhen / zipWith部分似乎正常工作。因为在存储库中,还有其他一些API调用,但没有重试行为(尚未),因此显示了SnackBar。这意味着,我需要进行另一个调用,在其中显示SnackBar->按钮单击,然后重试转换按预期工作。

如果您需要更多信息,请随时询问!任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:1)

很奇怪,只要您以正确的方式进行操作,它就会起作用。 我过度阅读了doOnError {...}中显示我的Snackbar所需的内容。

这是我的工作重试转换器:

<section>
  <nav>
    <ul>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Scroll to bottom</li>
      <li>Mouse in / out</li>
      <li>Watch me jump up / down</li>
     </ul>
   </nav>
</section>

现在链看起来像这样(我认为它很漂亮):

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)
                                }
                            })
                }
    }
}

我还需要将错误传播到ViewModel的第二个PublishSubject:

override fun loadMyData(): Observable<Resource<DataResponse>> {
    return retrofitApi
            .getMyData()
            .compose(getRetryTransformer())
            .toObservable()
            .compose(getResponseTransformer())
}

然后在ViewModel中观察它的变化并显示Snackbar。 而已。