2017-11-10 140 views
8

Kontrol edilmesi gereken 4 olası seçeneğe sahip bir formum var (koşullara bağlı olarak daha az olabilir). Bir sipariş oluştururken, biri e-posta için ve bir referans alanı için olmak üzere 2 adet editex vardır.RxJava2 form doğrulama

E-posta ve başvuru alanları, koşullara bağlı olarak boş bırakılabilir veya bırakılamaz (form oluşturulduğunda kullanılabilir). Ek olarak, kullanıcıya, referans değerini (siparişin alıcısına) göstermenin mümkün olmayacağını ve ayrıca bir şartlar ve durum uyarı iletişim kutusunu kabul etmesinin gerekebileceğini bildiren bir uyarı iletişim kutusu göstermemiz gerekebilir.

Şu onConfirm çekler, böyle bir şeydir

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(); 
} 

Ben RxJava2 ile bu doğrulama kolaylaştırmak için bir yol olup olmadığını bilmek isteriz? bence

TIA

cevap

3

(ama şu anda bunu yapabilmek için yeterince bilmiyorum) yapmanız gerekir RxJava CombineLatest, form girişinin hepsi sadece zaman size bir gözlemlenebilir üretiyoruz ihtiyaç yüzden bir referans olarak görünümü

birleştirin ve ayarlamak kontrol edebilirsiniz:

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

Using RxJava for email login validation, an observable is emitting twice

========

örnek:

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(); 
    }); 

    } 
} 
+0

sayesinde: doğrulayıcı için

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(); } } 

Yardımcısı sınıfları ... Başlangıçta

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; } } 

, buradan fikrini aldı: doğrulayıcı için

Özet sınıf

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 } 

! Metin değiştirme vb. Ile otomatik şeyler istemiyorum, sadece kullanıcı onaylama düğmesine tıkladığında doğrulamak istiyorum (çünkü uyarı iletişim kutularını açana kadar kontrol etmek istemediğim için) –

+0

daha sonra birleştirmeyi en son olarak onaylama düğmesi –

+0

içine koyun, bunun nasıl görüneceğine (iletişim kutusunun en az birinin görüntülenmesi gereken yere) ilişkin kısa bir parçacığı paylaşır mısınız? –

4

Bu basit olabilir. Çok fazla kod olacak, önce sonucu göstereceğim.

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... 
    } 

Birincisi, reviewState için model oluşturmak:

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; 
    } 
} 

Sonra doğrulayıcı kendi oluşturun. Bütün bir model oluşturmak gerekli değildir, her alan için doğrulayıcı oluşturabilir ve bunları seçtiğiniz flatMap() ile bağlayabilirsiniz. https://github.com/matzuk/TestableCodeMobius/tree/master/app/src/main/java/com/matsyuk/testablecodemobius/business/transfer/validation