2017-11-10 1 views
8

4 가지 가능한 옵션이있는 양식이 있습니다 (상황에 따라 더 적을 수 있음). 주문을 할 때 전자 메일과 참조 필드 용으로 두 개의 editexts가 있습니다.RxJava2 폼 유효성 검사

전자 메일 및 참조 필드는 조건 (양식을 만들 때 사용 가능)에 따라 비워 둘 수도 있고 그렇지 않을 수도 있습니다. 또한 (주문의 수신자에게) 참조 값을 표시 할 수 없으며 이용 약관 경고 대화 상자에 동의해야한다고 사용자에게 알리는 경고 대화 상자를 표시해야 할 수도 있습니다.

현재 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이 검증 간단하게 할 수있는 방법이 있는지 알고 싶어요? 내가 생각

TIA

답변

3

을 (그러나 현재이 작업을 수행 할 수있을만큼 모르는)을해야 RxJava CombineLatest, 폼 입력의 모든 그냥 다음, 당신을 관찰을 생산하고 필요하므로 참조로보기

그것을 결합하고 조정하면 확인할 수 있습니다

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

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

,

========하면

예 :

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

감사 : 검증을위한

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

도우미 클래스 ... 처음

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

, 여기에서 아이디어를했다 : 검증을위한

추상 클래스

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 } 

! 텍스트 변경 등으로 자동 작업을 원할 필요가 없습니다. 사용자가 확인 버튼을 클릭 할 때 유효성을 검사하기를 원합니다. (그 전에는 알림 대화 상자가 나타나는지 확인하고 싶지 않으므로) –

+0

확인 버튼 안에 콤비네이션을 넣으십시오. –

+0

대화 상자를 표시해야하는 상황을 간단하게 알려주십시오. –

4

이것은 간단 할 수있다. 많은 코드가있을 것이므로 먼저 결과를 보여 드리겠습니다.

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에 대한 모델을 만들 :

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

이 그럼 당신은 검증을 소유 만듭니다. 전체 모델을 만들 필요는 없으며 모든 필드에 대한 유효성 검사기를 만들고 원하는 flatMap()을 사용하여 연결할 수 있습니다. https://github.com/matzuk/TestableCodeMobius/tree/master/app/src/main/java/com/matsyuk/testablecodemobius/business/transfer/validation