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

Posted

技术标签:

【中文标题】如何在 RxJava 2 和 Android 中延迟 onError()?【英文标题】:How to delay onError() in RxJava 2 and Android? 【发布时间】:2018-05-15 18:27:38 【问题描述】:

我正在尝试从我的应用程序中的 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 秒后执行?谢谢

【问题讨论】:

你不能和Observable.timer(1, TimeUnit.SECONDS).switchMapSingle Single.fromCallable //... 一起去吗? mcassino 谢谢你这完美的作品。难道不能直接在 Single 上应用 timer() 操作符,而不是先将其转换为 Observable 吗? 你可以 :) 我认为 Single.timer() 然后 map() 也是一种有效的方法。 【参考方案1】:

感谢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】:

由于您的工作是在后台线程中完成的,您可以直接休眠而不冻结 ui:

SystemClock.sleep(1000)

把它放在hideLoader() 调用之前

【讨论】:

好主意,但这不是delay() 应该做的吗? 在延迟的文档中它说返回一个延迟源 ObservableSource 的发射的 Observable ..所以它延迟了发射,而不是执行。从理论上讲,您的代码可能会在我理解的延迟发射开始之前失败。【参考方案3】:

只需调用不同的延迟方法签名

public final Single<T> delay(long time, TimeUnit unit, boolean delayError)

Single.fromCallable 

    // http request logic goes here

.delay(1000, TimeUnit.MILLISECONDS, true)

【讨论】:

以上是关于如何在 RxJava 2 和 Android 中延迟 onError()?的主要内容,如果未能解决你的问题,请参考以下文章

RxJava入门系列四,Android中的响应式编程

Android RxJava小结

如何在 android 中使用 RxJava 在 Activity 之间传递数据?

Android——初识RxJava

Android编程:双工tcp客户端中应用RxJava

如何使用 Rxjava 在 Android Kotlin 中过滤数据