RxJava2 实战知识梳理(7) 基于 combineLatest 实现的输入表单验证

一、前言

2.1 应用背景

在平时的应用中,我们经常会让用户输入一些信息,最常见的莫过于注册或者登录界面中,让用户输入用户名或者密码,但是我们经常会对用户名或者密码有一定的要求,只有当它们同时满足要求时,才允许用户进行下一步的操作。

这个需求就涉及到一种模型,即在多个地方监听变化,但是在一个地方进行统一验证,如果验证成功,那么允许用户进行下一步的操作,否则提示用户输入不正确。

通过这个例子,大家将学习到combineLatest操作符的用法。

2.2 示例

在下面这个示例中,包含了两个输入框,分别对应用户名和密码,它们的长度要求分别为2~84~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最后一次发射的数据,我们通过该数据进行验证。

最终运行的效果为:

二、示例解析

2.1 combineLatest 原理

combineLatest的原理图如下所示:

该操作符接受多个 Observable以及一个函数作为参数,并且函数的签名为这些 Observable发射的数据类型。当以上的任意一个 Observable发射数据之后,会去取其它 Observable 最近一次发射的数据,回调到函数当中,但是该函数回调的前提是所有的 Observable至少发射过一个数据项

2.2 combineLatest 和 zip 的区别

zipcombineLatest接收的参数格式相同,我们在 RxJava2 实战知识梳理(4) - 结合 Retrofit 请求新闻资讯 中用它来实现等待多个Observable都发射之后才进行数据的组合,回顾一下它的原理图:

zipcombineLatest的区别在于:

  • zip是在其中一个Observable发射数据项后,组合所有Observable最早一个未被组合的数据项,也就是说,组合后的Observable发射的第n个数据项,必然是每个源由Observable各自发射的第n个数据项构成的。
  • combineLatest则是在其中一个Observable发射数据项后,组合所有Observable所发射的最后一个数据项(前提是所有的Observable都至少发射过一个数据项)。

更多文章,欢迎访问我的 Android 知识梳理系列:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值