Search code examples
androidmultithreadingrx-java2intervalsrx-android

What happens when an expensive operation is happening and thread freezes for longer than RxJava Interval period


I am using RxJava Interval Like this:

compositeDisposable.add(
    Observable.interval(1, TimeUnit.SECONDS)
        .flatMap(tick -> {
            return Observable.just(doWork(tick));
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(this::updateUI, e -> {
            disableIndicator();
            FirebaseCrashlytics.getInstance().recordException(e);
        })
);

public Status doWork(long tick) {
    // Doing heavy task
    // Here the Status is an Enum class
    return output
}

public void updateUI(Status value) {
    // Updates UI accordingly
}

Everything works as expected, but I have a concern. So my doWork() method is doing some heavy task in bg and I am updating the UI in updateUI() method based on the result produced by that method.I am calling the doWork() every second using RxJava Interval. Usually it takes less than a second to execute the doWork() method. So I was just wondering what happens if I have lots of data and the doWork() method takes more than one seconds to execute, lets say it takes 2 seconds.But the interval will keep calling the doWork() method every second. Since my previous execution will take another one second to complete what will I get as return value?


Solution

  • So the thing happens is something like this:

    • Suppose the method doWork takes longer than a second to execute the command, the next execution gets queued BUT NOT delayed.
    • Lets say in n th second the method does something expensive which takes 3 seconds to complete and will produce a result A. Since the method is being executed after 1 seconds, there will be another 3 execution which will be queued which will not take longer than a second to execute and produce and will generate result B,C,D.
    • After n+3 seconds you will get all four results at once. That will be A B C D

    So If you are hoping to see the result A at n+3 second and B C D after 1 seconds too (Means you don't want to get all four values at once), You need to do something like this:

    Observable.timer(1, TimeUnit.SECONDS)
        .flatMap(tick -> {
            return Observable.just(doWork());
        })
        .repeat()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(value -> printUI(value), throwable -> {})
    )