RxJava/RxAndroid - 处理多个 EditText 更改
RxJava/RxAndroid - handle multiple EditText changes
我有 3 个 EditText 字段,我为这些字段创建了 3 个可观察对象。
Observable<CharSequence> o1 = RxTextView.textChanges(field1);
Observable<CharSequence> o2 = RxTextView.textChanges(field2);
Observable<CharSequence> o3 = RxTextView.textChanges(field3);
我想在所有这三个字段都具有某些值时启用一个按钮。用户可以在字段中以任何顺序输入值。我该怎么做?
编辑
我使用 zip 实现了这一点。
Observable<CharSequence> o1 = RxTextView.textChanges(field1);
Observable<CharSequence> o2 = RxTextView.textChanges(field2);
Observable<CharSequence> o3 = RxTextView.textChanges(field3);
Observable.zip(o1, o2, o3, (c1, c2, c3) -> c1.length() > 0 && c2.length() > 0 && c3.length() > 0).subscribe(myButton::setEnabled)
当我在所有三个文本字段中输入内容时,上述案例有效。例如我在所有三个文本字段中输入了 1 个字符,然后按钮将被启用。但是当我在三个字段中的任何一个中删除一个字符时。 zip 将不会被调用,因为它将等待其他 2 个文本字段在调用订阅者的 onNext 之前流式传输一些数据。所以当我删除任何文本字段中的任何字符时,我希望我的按钮再次被禁用。我怎样才能做到这一点?
使用CombineLatest
代替zip
http://reactivex.io/documentation/operators/combinelatest.html
试试这个,这肯定会奏效。
使用 combineLatest.
//declare global variable
private Subscription subscription = null;
Observable<CharSequence> o1 = RxTextView.textChanges(field1);
Observable<CharSequence> o2 = RxTextView.textChanges(field2);
public void combineEvent(){
subscription = Observable.combineLatest(o1, o2,
new Func2<CharSequence, CharSequence, Boolean>() {
@Override public Boolean call(CharSequence newEmail, CharSequence newPassword) {
//here you can validate the edit text
boolean emailValid= !TextUtils.isEmpty(newEmail)
&& android.util.Patterns.EMAIL_ADDRESS.matcher(newEmail).matches();
if(!emailValid){
etEmailAddress.setError("Invalid Email");
}
boolean passValid = !TextUtils.isEmpty(newPassword)
&& newPassword.length() >6;
if(!passValid){
etPassword.setError("invalid password");
}
return emailValid && passValid;
}
}).subscribe(new Observer<Boolean>() {
@Override public void onCompleted() {
}
@Override public void onError(Throwable e) {
}
@Override public void onNext(Boolean aBoolean) {
if(aBoolean){
//here you can enable your button or what ever you want.
loginBtn.setEnabled(true);
}else {
loginBtn.setEnabled(false);
}
}
});
}
我有 3 个 EditText 字段,我为这些字段创建了 3 个可观察对象。
Observable<CharSequence> o1 = RxTextView.textChanges(field1);
Observable<CharSequence> o2 = RxTextView.textChanges(field2);
Observable<CharSequence> o3 = RxTextView.textChanges(field3);
我想在所有这三个字段都具有某些值时启用一个按钮。用户可以在字段中以任何顺序输入值。我该怎么做?
编辑
我使用 zip 实现了这一点。
Observable<CharSequence> o1 = RxTextView.textChanges(field1);
Observable<CharSequence> o2 = RxTextView.textChanges(field2);
Observable<CharSequence> o3 = RxTextView.textChanges(field3);
Observable.zip(o1, o2, o3, (c1, c2, c3) -> c1.length() > 0 && c2.length() > 0 && c3.length() > 0).subscribe(myButton::setEnabled)
当我在所有三个文本字段中输入内容时,上述案例有效。例如我在所有三个文本字段中输入了 1 个字符,然后按钮将被启用。但是当我在三个字段中的任何一个中删除一个字符时。 zip 将不会被调用,因为它将等待其他 2 个文本字段在调用订阅者的 onNext 之前流式传输一些数据。所以当我删除任何文本字段中的任何字符时,我希望我的按钮再次被禁用。我怎样才能做到这一点?
使用CombineLatest
代替zip
http://reactivex.io/documentation/operators/combinelatest.html
试试这个,这肯定会奏效。 使用 combineLatest.
//declare global variable
private Subscription subscription = null;
Observable<CharSequence> o1 = RxTextView.textChanges(field1);
Observable<CharSequence> o2 = RxTextView.textChanges(field2);
public void combineEvent(){
subscription = Observable.combineLatest(o1, o2,
new Func2<CharSequence, CharSequence, Boolean>() {
@Override public Boolean call(CharSequence newEmail, CharSequence newPassword) {
//here you can validate the edit text
boolean emailValid= !TextUtils.isEmpty(newEmail)
&& android.util.Patterns.EMAIL_ADDRESS.matcher(newEmail).matches();
if(!emailValid){
etEmailAddress.setError("Invalid Email");
}
boolean passValid = !TextUtils.isEmpty(newPassword)
&& newPassword.length() >6;
if(!passValid){
etPassword.setError("invalid password");
}
return emailValid && passValid;
}
}).subscribe(new Observer<Boolean>() {
@Override public void onCompleted() {
}
@Override public void onError(Throwable e) {
}
@Override public void onNext(Boolean aBoolean) {
if(aBoolean){
//here you can enable your button or what ever you want.
loginBtn.setEnabled(true);
}else {
loginBtn.setEnabled(false);
}
}
});
}