Heisenberg Heisenberg - 2 months ago 10
Android Question

RxJava operator that combines two observables and emits only when the first observable emits

I am new to

RxJava
and I am stuck with finding a right operator.
I want to have something like
combineLatest
, but only emit event when the first
Observable
emits an item and take the last item from the second
Observable
.
I am currently doing so using
BehaviourSubject
, but I would like to avoid having external variable if there is operator doing such thing.

What I have now:

BehaviorSubject<Login> inputSubject = BehaviorSubject.create();
Observable.
combineLatest(
RxTextView.textChanges(inputEmail.getEditText()),
RxTextView.textChanges(inputPassword.getEditText()),
Login::new)
.subscribe(inputSubject);
return RxView.clicks(loginBtn).map(v -> inputSubject.getValue());

Answer

You could use a second combineLatest:

Observable<Void> clicks = RxView.clicks(loginBtn);
Observable<Login> loginData = ...

class TaggedLogin {
    Object tag;
    Login data;

    TaggedLogin(Object tag, Login data) {
        this.tag = tag;
        this.data = data;
    }
}

return Observable.combineLatest(
    clicks.map(v -> new Object()), 
    loginData, 
    TaggedLogin::new
).distinctUntilChanged(tl -> tl.tag).map(tl -> tl.data);

The juggling with the tag is required because combineLatest will emit if either has a new value.

If you're willing to use Experimental features (aka RxJava might remove or change them in the future) then the following is possible:

Observable<Void> clicks = RxView.clicks(loginBtn);
Observable<Login> loginData = ...

return clicks.withLatestFrom(loginData, (v, data) -> data);