如何在RxJava 2和Android中延迟onError()方法?

5

我正在尝试在我的应用程序中从Web服务器加载一些数据。由于操作的异步性质,无法提前知道完成所需的时间。为了告诉用户操作“正在进行中”,我使用了一个加载指示器。

这是使用kotlin和RxJava 2开发的代码(希望很清晰):

fun loadData(){

    showLoader() // show loading indicator

    Single.fromCallable {

        // http request logic goes here

    }.delay(1000, TimeUnit.MILLISECONDS)
     .subscribeOn(Schedulers.io())
     .observeOn(AndroidSchedulers.mainThread())
     .subscribeWith(object : DisposableSingleObserver<String>() {

            override fun onSuccess(data: String) {
                // do something
                hideLoader() // on success, hide indicator
            }

            override fun onError(e: Throwable) {
                displayErrorMessage()
                hideLoader() // on error hide indicator
            }

      })
}

我希望能够展示至少1秒的加载指示器,因此我使用了delay()运算符,但问题在于,如果操作失败,指示器会立即消失而不是等待1秒后消失。

那么有没有办法让onError()方法在1秒后执行呢?谢谢。


1
你不能只使用 Observable.timer(1, TimeUnit.SECONDS).switchMapSingle { Single.fromCallable { //... } } 吗? - mcassiano
mcassino,谢谢您,这个代码完美运作。是否有可能直接将 timer() 运算符应用于 Single,而无需先将其转换为 Observable? - Toni Joe
你可以使用Single.timer()然后map()的方式来实现,这也是一种有效的方法。 - mcassiano
3个回答

3

感谢nacassiano的评论,我终于找到了解决方案:

fun loadData(){

    showLoader() // show loading indicator

    Single.timer(1000, TimeUnit.MILLISECONDS)
        .flatMap{
            Single.fromCallable {

                // http request logic goes here

            }
        }.subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribeBy( // this is an extension function from rxkotlin
            onSuccess = {
                // do something
                hideLoader() // on success, hide indicator
            },
            onError = {
                displayErrorMessage()
                hideLoader() // on error hide indicator
            }
       )
}

我希望这能对某些人有所帮助。

2
只需要调用不同的延迟方法签名。
public final Single<T> delay(long time, TimeUnit unit, boolean delayError)

即(i.e.)
Single.fromCallable {

    // http request logic goes here

}.delay(1000, TimeUnit.MILLISECONDS, true)

1

由于您的工作在后台线程中完成,因此可以直接休眠而不会冻结用户界面:

SystemClock.sleep(1000)

在调用hideLoader()之前加入这个


好主意,但这不是delay()函数的本意吗? - Toni Joe
在delay的文档中写道“返回一个Observable,它延迟了源ObservableSource的发射”。因此,它延迟了发射,而不是执行。理论上,在延迟发射启动之前,您的代码可能会失败,这就是我所理解的。 - donfuxx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接