RxJava2表单validation

我有一个需要检查的4个可能的选项(取决于具体情况可能会less一些)。 有两个editexts,一个用于电子邮件,一个用于创build订单时的参考字段。

根据条件(在创build表单时可用),电子邮件地址和参考字段可能会也可能不会被留空。 此外,我们可能需要显示一个警告对话框,告诉用户可能无法显示参考价值(订单的接收者),他们也可能需要同意条款和条件警报对话框。

目前onConfirm检查是这样的,

void onCreateOrderConfirmed(@Nullable final String receiverEmail, @Nullable final String reference, @Nullable final Boolean noRefAgreed, @Nullable final Boolean termsAndConditionsAgreed) { if (!reviewCompletionState.emailRequirementSatisfied()) { if (!isValidEmail(receiverEmail)) { view.showEmailError(); return; } reviewCompletionState = reviewCompletionState.newBuilder() .receiverEmail(receiverEmail) .emailRequirementSatisfied(true) .build(); } if (!reviewCompletionState.referenceRequirementSatisfied()) { if (isEmpty(reference)) { view.showReferenceError(); return; } reviewCompletionState = reviewCompletionState.newBuilder() .reference(reference) .referenceRequirementSatisfied(true) .build(); } if (!reviewCompletionState.noRefAgreed()) { if (noRefAgreed == null || !noRefAgreed) { view.showNoReferenceAlert(); return; } reviewCompletionState = reviewCompletionState.newBuilder() .noRefAgreed(true) .build(); } if (!reviewCompletionState.termsAndConditionsAgreed()) { if (termsAndConditionsAgreed == null || !termsAndConditionsAgreed) { view.showTermsDisclaimerAlert(); return; } reviewCompletionState = reviewCompletionState.newBuilder() .termsAndConditionsAgreed(true) .build(); } createOrder(); } 

我很想知道是否有一种方法可以使RxJava2的validation更简单? (但是目前不知道能够做到这一点)

TIA

Related of "RxJava2表单validation"

我认为你应该RxJava CombineLatest ,所以你需要所有的表单input都产生一个可观察的,然后你只是结合它,并调整视图

作为参考你可以检查:

https://medium.com/@etiennelawlor/rxjava-on-the-sign-in-screen-9ecb66b88572

使用RxJava进行电子邮件loginvalidation,observable发出两次

========

例:

 import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; import com.jakewharton.rxbinding2.view.RxView; import com.jakewharton.rxbinding2.widget.RxCompoundButton; import com.jakewharton.rxbinding2.widget.RxTextView; import io.reactivex.Observable; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); EditText receiverText = findViewById(R.id.input_receiver); EditText referenceText = findViewById(R.id.input_reference); CheckBox checkRef = findViewById(R.id.check_ref); CheckBox checkTerms = findViewById(R.id.check_terms); Button buttonLogin = findViewById(R.id.button_login); Observable<CharSequence> receiverObservable = RxTextView.textChanges(receiverText).skip(1); // can add more logic Observable<CharSequence> referenceObservable = RxTextView.textChanges(referenceText).skip(1); // can add more logic Observable<Boolean> refCheckObservable = RxCompoundButton.checkedChanges(checkRef); // can add more logic Observable<Boolean> termsCheckObservable = RxCompoundButton.checkedChanges(checkTerms); // can add more logic Observable<String> combineObservable = Observable.combineLatest( receiverObservable, referenceObservable, refCheckObservable, termsCheckObservable, (receiverCharSequence, referenceCharSequence, refBoolean, termsBoolean) -> { // add logic here for now it is only combine the input return receiverCharSequence + " " + referenceCharSequence + " " + refBoolean + " " + termsBoolean ;} ); RxView.clicks(buttonLogin).flatMap(o -> { return combineObservable;}).distinctUntilChanged().subscribe(string -> { Toast.makeText(this, string, Toast.LENGTH_LONG).show(); }); } } 

这可以是一个简单的。 会有很多代码,我会先显示结果。

  private ReviewValidator reviewValidator = new ReviewValidator(); void onCreateOrderConfirmed(@Nullable final String receiverEmail, @Nullable final String reference, @Nullable final Boolean noRefAgreed, @Nullable final Boolean termsAndConditionsAgreed) { ReviewState reviewState = new ReviewState(receiverEmail, reference, noRefAgreed, termsAndConditionsAgreed);//another model for simplicity reviewValidator.validate(reviewState) .flatMap(reviewState -> /* create order */) .subscribe(this::onOrderCreated, this::onOrderCreatingError); } void onOrderCreated(Object order) {//or what you need here //handle positive result } void onOrderCreatingError(Throwable throwable) { if (throwable instanceof ValidateException) { List<ValidateError> errors = ((ValidateException) throwable).getValidateErrors(); for (ValidateError error: errors) { switch (error.getField()) { case EMAIL: { view.showEmailError(); return;//or break if you want show all errors } case REFERENCE: { view.showReferenceError(); return; } //handle another errors.... } } //handle another error cases... } 

首先,为reviewState创build模型:

 public class ReviewState { private String receiverEmail; private String reference; private Boolean noRefAgreed; private Boolean termsAndConditionsAgree; public ReviewState(String receiverEmail, String reference, Boolean noRefAgreed, Boolean termsAndConditionsAgree) { this.receiverEmail = receiverEmail; this.reference = reference; this.noRefAgreed = noRefAgreed; this.termsAndConditionsAgree = termsAndConditionsAgree; } public String getReceiverEmail() { return receiverEmail; } public String getReference() { return reference; } public Boolean getNoRefAgreed() { return noRefAgreed; } public Boolean getTermsAndConditionsAgree() { return termsAndConditionsAgree; } } 

然后创build你自己的validation器。 没有必要创build一个完整的模型,你可以为每个字段创buildvalidation器,并将它们与你select的flatMap()链接起来。

 public class ReviewValidator extends Validator<ReviewState> { @Override protected List<ValidateFunction> getValidateFunctions(ReviewState reviewState) { List<ValidateFunction> validateFunctions = new LinkedList<>(); validateFunctions.add(() -> validateEmail(reviewState.getReceiverEmail())); validateFunctions.add(() -> validateReference(reviewState.getReference())); //another validation methods return validateFunctions; } private ValidateError validateEmail(String email) { if (TextUtils.isEmpty(email)) { return new ValidateError(Field.EMAIL);//Field.EMAIL - just enum } return null; } private ValidateError validateReference(String reference) { if (TextUtils.isEmpty(reference)) { return new ValidateError(Field.REFERENCE); } return null; } //.... //another validation methods } 

validation器的抽象类:

 public abstract class Validator<Model> { public Single<Model> validate(Model model) { return Single.just(model) .map(this::validateModel) .flatMap(this::processResult); } private Single<Model> processResult(ValidateResultModel<Model> validateResultModel) { return Single.create(subscriber -> { List<ValidateError> validateErrors = validateResultModel.getValidateErrors(); if (validateErrors.isEmpty()) { subscriber.onSuccess(validateResultModel.getModel()); } else { subscriber.onError(new ValidateException(validateErrors)); } }); } private ValidateResultModel<Model> validateModel(Model model) { List<ValidateError> errors = new LinkedList<>(); for (ValidateFunction validateFunctions : getValidateFunctions(model)) { ValidateError error = validateFunctions.validate(); if (error != null) { errors.add(error); } } return new ValidateResultModel<>(model, errors); } protected abstract List<ValidateFunction> getValidateFunctions(Model model); protected interface ValidateFunction { @Nullable ValidateError validate(); } } 

助手类validation程序…

 public class ValidateError { private Field field; public ValidateError(Field field) { this.field = field; } public Field getField() { return field; } } class ValidateResultModel<T> { private T model; private List<ValidateError> validateErrors; ValidateResultModel(T model, List<ValidateError> validateErrors) { this.model = model; this.validateErrors = validateErrors; } T getModel() { return model; } List<ValidateError> getValidateErrors() { return validateErrors; } } public class ValidateException extends RuntimeException { private List<ValidateError> validateErrors; ValidateException(List<ValidateError> validateErrors) { this.validateErrors = validateErrors; } public List<ValidateError> getValidateErrors() { return validateErrors; } } 

最初,我从这里采取了这个想法: https : //github.com/matzuk/TestableCodeMobius/tree/master/app/src/main/java/com/matsyuk/testablecodemobius/business/transfer/validation