RxJava2 實戰知識梳理(7) 基於 combineLatest 實現的輸入表單驗證

1、前言

2.1 應用背景

在平時的應用中,咱們常常會讓用戶輸入一些信息,最多見的莫過於註冊或者登陸界面中,讓用戶輸入用戶名或者密碼,可是咱們常常會對用戶名或者密碼有必定的要求,只有當它們同時知足要求時,才容許用戶進行下一步的操做。java

這個需求就涉及到一種模型,即在多個地方監聽變化,可是在一個地方進行統一驗證,若是驗證成功,那麼容許用戶進行下一步的操做,不然提示用戶輸入不正確。app

經過這個例子,你們將學習到combineLatest操做符的用法。ide

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最後一次發射的數據,咱們經過該數據進行驗證。學習

最終運行的效果爲: spa

2、示例解析

2.1 combineLatest 原理

combineLatest的原理圖以下所示: code

combineLatest 原理圖
該操做符接受多個 Observable以及一個函數做爲參數,而且函數的簽名爲這些 Observable發射的數據類型。當以上的任意一個 Observable發射數據以後,會去取其它 Observable 最近一次發射的數據,回調到函數當中,可是該函數回調的前提是全部的 Observable至少發射過一個數據項

2.2 combineLatest 和 zip 的區別

zipcombineLatest接收的參數格式相同,咱們在 RxJava2 實戰知識梳理(4) - 結合 Retrofit 請求新聞資訊 中用它來實現等待多個Observable都發射以後才進行數據的組合,回顧一下它的原理圖: cdn

zip 原理圖
zipcombineLatest的區別在於:

  • zip是在其中一個Observable發射數據項後,組合全部Observable最先一個未被組合的數據項,也就是說,組合後的Observable發射的第n個數據項,必然是每一個源由Observable各自發射的第n個數據項構成的。
  • combineLatest則是在其中一個Observable發射數據項後,組合全部Observable所發射的最後一個數據項(前提是全部的Observable都至少發射過一個數據項)。

更多文章,歡迎訪問個人 Android 知識梳理系列:

相關文章
相關標籤/搜索