在平时的应用中,咱们常常会让用户输入一些信息,最多见的莫过于注册或者登陆界面中,让用户输入用户名或者密码,可是咱们常常会对用户名或者密码有必定的要求,只有当它们同时知足要求时,才容许用户进行下一步的操做。java
这个需求就涉及到一种模型,即在多个地方监听变化,可是在一个地方进行统一验证,若是验证成功,那么容许用户进行下一步的操做,不然提示用户输入不正确。app
经过这个例子,你们将学习到combineLatest
操做符的用法。ide
在下面这个示例中,包含了两个输入框,分别对应用户名和密码,它们的长度要求分别为2~8
和4~16
,若是二者都正确,那么登陆按钮的文案变为“登陆”,不然显示“用户名或密码无效”。函数
public class CombineLatestActivity extends AppCompatActivity {
private EditText mEtName;
private EditText mEtPassword;
private Button mBtLogin;
private PublishSubject<String> mNameSubject;
private PublishSubject<String> mPasswordSubject;
private CompositeDisposable mCompositeDisposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_combine_latest);
mEtName = (EditText) findViewById(R.id.et_name);
mEtPassword = (EditText) findViewById(R.id.et_password);
mBtLogin = (Button) findViewById(R.id.bt_login);
mNameSubject = PublishSubject.create();
mPasswordSubject = PublishSubject.create();
mEtName.addTextChangedListener(new EditTextMonitor(mNameSubject));
mEtPassword.addTextChangedListener(new EditTextMonitor(mPasswordSubject));
Observable<Boolean> observable = Observable.combineLatest(mNameSubject, mPasswordSubject, new BiFunction<String, String, Boolean>() {
@Override
public Boolean apply(String name, String password) throws Exception {
int nameLen = name.length();
int passwordLen = password.length();
return nameLen >= 2 && nameLen <= 8 && passwordLen >= 4 && passwordLen <= 16;
}
});
DisposableObserver<Boolean> disposable = new DisposableObserver<Boolean>() {
@Override
public void onNext(Boolean value) {
mBtLogin.setText(value ? "登陆" : "用户名或密码无效");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
observable.subscribe(disposable);
mCompositeDisposable = new CompositeDisposable();
mCompositeDisposable.add(disposable);
}
private class EditTextMonitor implements TextWatcher {
private PublishSubject<String> mPublishSubject;
EditTextMonitor(PublishSubject<String> publishSubject) {
mPublishSubject = publishSubject;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
mPublishSubject.onNext(s.toString());
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mCompositeDisposable.clear();
}
}
复制代码
在上面的例子中,咱们首先建立了两个PublishSubject
,分别用于用户名和密码的订阅,而后经过combineLatest
对这两个PublishSubject
进行组合。这样,当任意一个PublishSubject
发送事件以后,就会回调combineLatest
最后一个函数的apply
方法,该方法会取到每一个被观察的PublishSubject
最后一次发射的数据,咱们经过该数据进行验证。学习
最终运行的效果为: spa
combineLatest
的原理图以下所示: code
Observable
以及一个函数做为参数,而且函数的签名为这些
Observable
发射的数据类型。当以上的任意一个
Observable
发射数据以后,会去取其它
Observable
最近一次发射的数据,回调到函数当中,可是该函数回调的前提是全部的
Observable
都
至少发射过一个数据项。
zip
和combineLatest
接收的参数格式相同,咱们在 RxJava2 实战知识梳理(4) - 结合 Retrofit 请求新闻资讯 中用它来实现等待多个Observable
都发射以后才进行数据的组合,回顾一下它的原理图: cdn
zip
和
combineLatest
的区别在于:
zip
是在其中一个Observable
发射数据项后,组合全部Observable
最先一个未被组合的数据项,也就是说,组合后的Observable
发射的第n
个数据项,必然是每一个源由Observable
各自发射的第n
个数据项构成的。combineLatest
则是在其中一个Observable
发射数据项后,组合全部Observable
所发射的最后一个数据项(前提是全部的Observable
都至少发射过一个数据项)。