Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delay onError() in RxJava 2 and Android?

Tags:

I'm Trying to load some data from a web server in my application. And Because of the async nature of the operation, there is no way to know ahead of time how long it will take to complete. To alert the user that the operation is “in progress.”, I'am using a loading indicator.

This is the a came up with using kotlin and RxJava 2 ( I hope it's clear):

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
            }

      })
}

I want to show the loading indicator for at least 1 second so I used the delay() operator, but the problem is this works as expected if the operation succeeded, but in case of an error, the indicator will disappear immediately not after 1 second.

So is there a way I can make the onError() method execute after 1 second? Thanks

like image 852
Toni Joe Avatar asked Dec 01 '17 15:12

Toni Joe


2 Answers

Thanks to nacassiano comment, I finally manage to find a solution:

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

I hope this will help someone.

like image 113
Toni Joe Avatar answered Sep 23 '22 13:09

Toni Joe


Just call a different delay method signature

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)
like image 37
manwtein Avatar answered Sep 23 '22 13:09

manwtein