Reputation: 19824
I've just began trying to learn RxJava / RxAndroid here and I am trying to validate a form. I used Kaushik Gopal's lovely example here and got my edit texts working with the combineLatest
subscription nicely. Now I want to observe something else as part of the same subscription. I have a button to choose a date of birth which returns it's result in my Fragment's onActivityResult() function. What kind of observer do I need for that?
private Observable<CharSequence> mNameChangeObservable; //etc.
private Observable<Date> mDateChangeObservable;
OnCreateView():
mIDNumberChangeObservable = RxTextView.textChanges(mIDNumberEditText).skip(1);
mNameChangeObservable = RxTextView.textChanges(mNameEditText).skip(1);
mEmailChangeObservable = RxTextView.textChanges(mEmailEditText).skip(1);
mPasswordChangeObservable = RxTextView.textChanges(mPasswordEditText).skip(1);
//mDateChangeObservable = ???;
Subscription:
private void combineLatestEvents() {
mSubscription = Observable.combineLatest(mLLNumberChangeObservable,
mNameChangeObservable,
mEmailChangeObservable,
mPasswordChangeObservable,
mDateChangeObservable,
new Func5<CharSequence, CharSequence, CharSequence, CharSequence, Date, Boolean>() {
@Override
public Boolean call(CharSequence newIDNumber,
CharSequence newName,
CharSequence newEmail,
CharSequence newPassword,
Date newDate) {
boolean idNumberValid = !isEmpty(newIDNumber) && newIDNumber.length() == 8;
if (!idNumberValid) {
mLLNumberEditText.setError("Invalid ID Number!");
}
boolean nameValid = !isEmpty(newName);
if (!nameValid) {
mNameEditText.setError("Invalid Name!");
}
boolean emailValid = !isEmpty(newEmail) &&
EMAIL_ADDRESS.matcher(newEmail).matches();
if (!emailValid) {
mEmailEditText.setError("Invalid Email!");
}
boolean passValid = !isEmpty(newPassword) && newPassword.length() >= 8;
if (!passValid) {
mPasswordEditText.setError("Invalid Password!");
}
//Validate Date
return idNumberValid && nameValid && emailValid && passValid;
}
})//
.subscribe(new Observer<Boolean>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Boolean formValid) {
if (formValid) {
mSubmitButton.setEnabled(true);
} else {
//Also print error here
mSubmitButton.setEnabled(false);
}
}
});
}
OnActivityResult:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) return;
if (requestCode == REQUEST_DATE) {
mDate = (Date) data.getSerializableExtra(Constants.Extras.EXTRA_DATE);
updateDobButtonText(mDate);
//Somehow tell my subscription I have a new date
}
}
Upvotes: 2
Views: 1034
Reputation: 19824
Okay after a hell of a lot more Googling I've come to the conclusion that the normal way to hook in to lifecycle events would be to use Trello's RxLifeCycle library. However because I just want to fire a simple synchronous event and I know precisely when (during onActivityResult), this is the solution I have found:
(1) Create a Subject - in this case I think a PublishSubject is best because it's only one object that needs emitting.
private PublishSubject<Date> mDateSubject = PublishSubject.create();
(2) Convert it to an Observable which will listen for events on the main thread.
public Observable<Date> makeDateObservable() {
return mDateSubject.observeOn(AndroidSchedulers.mainThread());
}
(3) Emit the object by calling next() on the subject when we have it:
mDateSubject.onNext(mDate);
Upvotes: 0
Reputation: 31996
You can follow your current pattern to get events from a button. Button
is a subclass of TextView
, so you can call RxTextView.textChanges()
with a Button
as a parameter. It will emit items when the button text changes. Specifically, if this line
updateDobButtonText(mDate);
calls Button.setText()
, you should get the event on your subscriber.
Upvotes: 1