Sto facendo un semplice modulo di accesso (e-mail e password) per cercare di rafforzare il mio skillset di programmazione reattiva. Sto avendo qualche problema a far funzionare la convalida del campo email nel modo in cui lo voglio.Utilizzando RxJava per la convalida dell'accesso alla posta elettronica, un osservabile emette due volte
Ecco il mio codice:
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));
Ed ecco il registro:
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:
Come si può vedere, emailIsValid
è chiamato due volte ogni volta che si digita un carattere, il che significa che sta facendo un regex match due volte, che è una specie di spreco.
ho guardato come avrei potuto fare emailIsValid
chiamare una sola volta per il cambiamento, non importa quanti abbonati ha, e ho trovato il metodo share()
. Ecco cosa accade quando aggiungo .share()
alla fine della dichiarazione emailIsValid
s':
emailIsValid call: // I type 'j' emailIsValid call: j valid: false, password: // I type 'a' emailIsValid call: ja valid: false, password:
che risolve il problema, ma provoca un altro: non c'è emettono iniziale emailIsValid
alla funzione combineLatest
alla fine, quindi il pulsante Login viene abilitato, quando deve essere disattivato (visualizzato in grigio).
Qual è il modo più pulito per risolvere questo problema? I penso Voglio che si comporti come un BehaviorSubject
, ma non sono sicuro se questo è il modo migliore per farlo.
Impressionante, non era a conoscenza di osservabili collegabili. Funziona bene, grazie! –
@ D_Steve595 NP. Sono contento di poterti aiutare! – pt2121