Android Rx: Conditioned timer of emitter

77 Views Asked by At

I have BehaviorSubject<Boolean> and I wonder how to get the following behaviour:

  • When comes False it should wait for 10 sec before emit the value
  • When comes True it emits the value immediately, and also cancel previous 10 sec timer if exist
3

There are 3 best solutions below

2
akarnokd On

You'll need a flatMap to introduce a delay and a takeUntil wired into it to cancel it when a true appears.

var subject = ...

subject.flatMap(value -> {
    if (value) {
        return Observable.just(true);
    }
    return Observable.just(false)
                     .delay(10, TimeUnit.SECONDS)
                     .takeUntil(
                         subject.filter(value2 -> value2)
                     );
});
1
Dawid Czopek On
private val subject = BehaviorSubject.create<Boolean>()

private fun testSubject() {
    subject
        .doOnNext { println("onNext: $it") }
        .debounce {
            if (it) Observable.empty<Boolean>()
            else Observable.timer(10, TimeUnit.SECONDS)
        }
        .subscribe {
            println("Received $it")
        }
}
0
Maveňツ On

Utilize RxJava operators and adjust how you handle BehaviorSubject changes. Here's how you can implement it:

import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
import java.util.concurrent.TimeUnit;


BehaviorSubject < Boolean > subject = BehaviorSubject.createDefault(false);

subject
    .flatMap(value - > {
        if (value) {
            return Observable.just(value);
        } else {
            return Observable.just(value)
                .delay(10, TimeUnit.SECONDS)
                .takeUntil(subject.filter(cancel - > cancel));
        }
    })
    .subscribe(System.out::println);

// Simulate updates BehaviorSubject
subject.onNext(true); // Should emit immediately
Thread.sleep(3000);
subject.onNext(false); // Should wait 10 seconds before emitting
Thread.sleep(5000);
subject.onNext(true); // Should cancel previous delay and emit immediately

Thread.sleep(15000); // Wait for remaining 5 seconds in first delay

// Ensure that the program continues running
subject.onComplete();
  • Make subject a BehaviorSubject manage our boolean values.
  • Alternate between emitting the value instantly and postponing emission, utilize flatMap operator.
  • Using Observable.just(value), we emit the value instantly when it is {true}.
  • We use {Observable.just(value).delay(10, TimeUnit.SECONDS)} postpone emission by 10 seconds when the value is false. Additionally, in the event that a later true value is obtained, we employ takeUntil end the wait. We mimic change {BehaviorSubject} by using various values when we use onNext(true/false).

It can be achieved with this setup: emitting {true} values right away while canceling any prior delay, and waiting for 10 seconds before emitting `false} values.