Last active
January 7, 2019 03:27
-
-
Save mandybess/90503fea3eace85f5c31fb1982346fc6 to your computer and use it in GitHub Desktop.
RxJava + MVP Sign up Form Validation Take Two
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
port android.app.Activity; | |
import android.os.Bundle; | |
import android.widget.Button; | |
import android.widget.EditText; | |
import club.smartsavers.presenters.SignUpPresenter; | |
import club.smartsavers.presenters.SignUpPresenterImpl; | |
import com.jakewharton.rxbinding.widget.RxTextView; | |
import rx.Observable; | |
public class SignUpActivity extends Activity implements SignUpView { | |
EditText firstName; | |
EditText lastName; | |
EditText email; | |
EditText zipCode; | |
EditText password; | |
Button submitButton; | |
SignUpPresenter presenter; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
//must inflate views before presenter | |
presenter = new SignUpPresenterImpl(this); | |
} | |
@Override | |
public void showProgress() { | |
} | |
@Override | |
public void hideProgress() { | |
} | |
@Override | |
public void showFirstNameError(CharSequence error) { | |
firstName.setError(error); | |
} | |
@Override | |
public void showLastNameError(CharSequence error) { | |
lastName.setError(error); | |
} | |
@Override | |
public void showEmailError(CharSequence error) { | |
email.setError(error); | |
} | |
@Override | |
public void showZipCodeError(CharSequence error) { | |
zipCode.setError(error); | |
} | |
@Override | |
public void showPasswordError(CharSequence error) { | |
password.setError(error); | |
} | |
@Override | |
public void navigateToMainScreen() { | |
} | |
@Override | |
public void updateSubmitButtonViewState(boolean enabled) { | |
submitButton.setEnabled(enabled); | |
} | |
@Override | |
public Observable<CharSequence> firstName() { | |
return RxTextView.textChanges(firstName); | |
} | |
@Override | |
public Observable<CharSequence> lastName() { | |
return RxTextView.textChanges(lastName); | |
} | |
@Override | |
public Observable<CharSequence> email() { | |
return RxTextView.textChanges(email); | |
} | |
@Override | |
public Observable<CharSequence> zipCode() { | |
return RxTextView.textChanges(zipCode); | |
} | |
@Override | |
public Observable<CharSequence> password() { | |
return RxTextView.textChanges(password); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import club.smartsavers.R; | |
import club.smartsavers.views.SignUpView; | |
import rx.Observable; | |
import rx.functions.Action1; | |
import rx.functions.Func1; | |
import rx.functions.Func5; | |
public class SignUpPresenter implements Presenter<SignUpView> { | |
private SignUpView signUpView; | |
private final Context context; | |
public SignUpPresenter(Context context) { | |
this.context = context; | |
} | |
public Func1<CharSequence, Boolean> isFirstNameValid() { | |
return textViewAfterTextChangeEvent -> FIRST_NAME_VALIDITY_CHECK; | |
} | |
public Action1<Boolean> updateFirstNameViewState() { | |
return isValid -> { | |
if (!isValid) { | |
signUpView.showFirstNameError(context.getString(R.string.first_name_field_validity_error)); | |
} | |
}; | |
} | |
public Func1<CharSequence, Boolean> isLastNameValid() { | |
return textViewAfterTextChangeEvent -> LAST_NAME_VALIDITY_CHECK; | |
} | |
public Action1<Boolean> updateLastNameViewState() { | |
return isValid -> { | |
if (!isValid) { | |
signUpView.showLastNameError(context.getString(R.string.last_name_field_validity_error)); | |
} | |
}; | |
} | |
public Func1<CharSequence, Boolean> isEmailValid() { | |
return textViewAfterTextChangeEvent -> EMAIL_VALIDITY_CHECK; | |
} | |
public Action1<Boolean> updateEmailViewState() { | |
return isValid -> { | |
if (!isValid) { | |
signUpView.showEmailError(context.getString(R.string.email_field_validity_error)); | |
} | |
}; | |
} | |
public Func1<CharSequence, Boolean> isZipCodeValid() { | |
return textViewAfterTextChangeEvent -> ZIPCODE_VALIDITY_CHECK; | |
} | |
public Action1<Boolean> updateZipCodeViewState() { | |
return isValid -> { | |
if (!isValid) { | |
signUpView.showZipCodeError(context.getString(R.string.zipcode_field_validity_error)); | |
} | |
}; | |
} | |
public Func1<CharSequence, Boolean> isPasswordValid() { | |
return textViewAfterTextChangeEvent -> PASSWORD_VALIDITY_CHECK; | |
} | |
public Action1<Boolean> updatePasswordViewState() { | |
return isValid -> { | |
if (!isValid) { | |
signUpView.showPasswordError(context.getString(R.string.password_field_validity_error)); | |
} | |
}; | |
} | |
public Func5<Boolean, Boolean, Boolean, Boolean, Boolean, Boolean> isFormValid() { | |
return (isFirsNameValid, isLastNameValid, isEmailValid, isZipCodeValid, isPasswordValid) -> | |
isFirsNameValid | |
&& isLastNameValid | |
&& isEmailValid | |
&& isZipCodeValid | |
&& isPasswordValid; | |
} | |
@Override | |
public void attachView(SignUpView mvpView) { | |
signUpView = mvpView; | |
Observable<Boolean> firstNameObservable = signUpView.firstName().map(isFirstNameValid()); | |
Observable<Boolean> lastNameObservable = signUpView.lastName().map(isLastNameValid()); | |
Observable<Boolean> emailObservable = signUpView.email().map(isEmailValid()); | |
Observable<Boolean> zipCodeObservable = signUpView.zipCode().map(isZipCodeValid()); | |
Observable<Boolean> passwordObservable = signUpView.password().map(isPasswordValid()); | |
firstNameObservable.subscribe(updateFirstNameViewState()); | |
lastNameObservable.subscribe(updateLastNameViewState()); | |
emailObservable.subscribe(updateEmailViewState()); | |
zipCodeObservable.subscribe(updateZipCodeViewState()); | |
passwordObservable.subscribe(updatePasswordViewState()); | |
Observable.combineLatest(firstNameObservable, lastNameObservable, emailObservable, | |
zipCodeObservable, passwordObservable, isFormValid()).subscribe(isValid -> { | |
signUpView.updateSubmitButtonViewState(isValid); | |
}); | |
} | |
@Override | |
public void detachView() { | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import rx.Observable; | |
public interface SignUpView extends BaseView { | |
void showProgress(); | |
void hideProgress(); | |
Observable<CharSequence> firstName(); | |
Observable<CharSequence> lastName(); | |
Observable<CharSequence> email(); | |
Observable<CharSequence> zipCode(); | |
Observable<CharSequence> password(); | |
void showFirstNameError(CharSequence error); | |
void showLastNameError(CharSequence error); | |
void showEmailError(CharSequence error); | |
void showZipCodeError(CharSequence error); | |
void showPasswordError(CharSequence error); | |
void updateSubmitButtonViewState(boolean enabled); | |
void navigateToMainScreen(); | |
} |
Why don't you return the ResId of string in the presenter and u can leave the context where it belongs to.
I don't think that you can pass Context to presenter , since Context is from android.* and you can't use android.* in presenter you have to decouple the presenter class from android API completely
I don't think that you can pass Context to presenter , since Context is from android.* and you can't use android.* in presenter you have to decouple the presenter class from android API completely
I agree with you, as far as I know context should not pass to the presenter.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Not sure you are using multiple subscriptions or not on TextView. But if so then it might cause concurrency issue whenever any subscriber faces error.