Tworzę prosty formularz logowania (e-mail i hasło), aby wzmocnić mój zestaw umiejętności programowania reaktywnego. Mam problem z uzyskaniem sprawdzania poprawności adresu e-mail, aby działał tak, jak chcę.Używanie RxJava do sprawdzania poprawności logowania przez e-mail, obserwowalny emituje dwa razy
Oto mój kod:
final Observable<CharSequence> email = RxTextView.textChanges(emailView);
Observable<Boolean> emailIsValid = email.map(new Func1<CharSequence, Boolean>() {
@Override
public Boolean call(CharSequence charSequence) {
Log.d("asdf", "emailIsValid call: " + charSequence);
return Pattern.matches(Patterns.EMAIL_ADDRESS.pattern(), charSequence);
}
});
RxView.focusChanges(emailView)
.withLatestFrom(emailIsValid, new Func2<Boolean, Boolean, Boolean>() {
@Override
public Boolean call(Boolean hasFocus, Boolean emailIsValid) {
return (!hasFocus && !emailIsValid);
}
})
.subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean showError) {
if (showError) {
emailInputLayout.setError("Enter a valid email");
} else {
emailInputLayout.setError(null);
}
}
});
Observable<CharSequence> password = RxTextView.textChanges(passwordView);
Observable.combineLatest(emailIsValid, password,
new Func2<Boolean, CharSequence, Boolean>() {
@Override
public Boolean call(Boolean emailIsValid, CharSequence password) {
Log.d("asdf", "valid: " + emailIsValid + ", password: " + password);
return (emailIsValid && password.length() > 0);
}
})
.subscribe(RxView.enabled(loginButton));
A oto log:
emailIsValid call: emailIsValid call: valid: false, password: // I type 'j' emailIsValid call: j emailIsValid call: j valid: false, password: // I type 'a' emailIsValid call: ja emailIsValid call: ja valid: false, password:
Jak widać, emailIsValid
nazywany jest dwa razy za każdym razem wpisuję charakter, co oznacza, że to robi regex match dwa razy, co jest trochę nieekonomiczne.
Sprawdziłem, jak mogę wykonać emailIsValid
dzwonić tylko raz na zmianę, bez względu na to, ilu abonentów ma, i znalazłem metodę share()
. Oto co się dzieje, gdy dodam .share()
do końca deklaracji emailIsValid
„s:
emailIsValid call: // I type 'j' emailIsValid call: j valid: false, password: // I type 'a' emailIsValid call: ja valid: false, password:
To rozwiązuje problem, ale powoduje inny: Nie ma początkowy emitować przez emailIsValid
do funkcji combineLatest
na końcu, więc przycisk logowania jest włączony, kiedy powinien być wyłączony (wyszarzony).
Jaki jest najczystszy sposób rozwiązania tego problemu? I think Chcę, aby zachowywał się jak BehaviorSubject
, ale nie jestem pewien, czy to najlepszy sposób to zrobić.
Niesamowite, nie wiedział o możliwych do zaobserwowania sprzężeniach. Działa dobrze, dziękuję! –
@ D_Steve595 NP. Cieszę się, że mogę pomóc! – pt2121