了解RxJava + Kotlin中的CompositeDisposable

时间:2019-08-28 08:49:41

标签: android kotlin rx-java android-lifecycle rx-binding

我正在使用RxJava进行表单验证以验证用户名和密码。 我的用例很简单,如果两个字段都满足各自的条件,则启用登录按钮,否则将其禁用。 以下是我的代码。


    lateinit var subscriptions: CompositeDisposable
    private fun validateForm() {
        val emailObservable = viewBinding.detUserName.editText.textChangeEvents()
            .skipInitialValue()
            .map { isValidEmail(it.text) || isValidPhoneNumber(it.text) }
            .doOnDispose {
                Log.i("disposed", "emailObservable")
            }


        val passwordObservable = viewBinding.detPassword.editText.textChangeEvents()
            .skipInitialValue()
            .map { !TextUtils.isEmpty(it.text) }
            .doOnDispose {
                Log.i("disposed", "passwordObservable")
            }

        val disposable = Observable.combineLatest(emailObservable, passwordObservable,
            BiFunction<Boolean, Boolean, Boolean> { t1, t2 -> t1 && t2 }).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                viewBinding.bLogin.isEnabled = it
            }
        subscriptions.add(disposable)
    }

fun isValidEmail(target: CharSequence): Boolean {
        return !TextUtils.isEmpty(target) && android.util.Patterns.EMAIL_ADDRESS.matcher(target).matches()
    }

    fun isValidPhoneNumber(target: CharSequence): Boolean {
        return !TextUtils.isEmpty(target) && Pattern.compile("(05|9665)[0-9]{8}").matcher(target).matches()
    }

订阅是我在onCreate和onResume中创建的CompositeDisposable对象引用(如果未创建或已经清除/处置) 并将其放在onStop()

修改

以下是我基本片段的一部分

 override fun onResume() {
        super.onResume()
        createDisposable()
    }

    protected fun createDisposable() {
        if (!this::subscriptions.isInitialized) {
            subscriptions = CompositeDisposable()
        }
    }
   override fun onStop() {
        super.onStop()
        disposeAll()
    }

    protected fun disposeAll() {
        if (this::subscriptions.isInitialized) {
            subscriptions.clear()
        }
    }

我的登录片段

override fun onResume() {
        super.onResume()
        validateForm()
    }

Observable.combineLatest 第一次正常运行,但问题在于该应用进​​入后台并恢复运行后不再触发。 当它进入后台时,onStop()调用会清除所有一次性用品的CompositeDisposable处理方式,当它恢复时,我仍将新的一次性用品实例重新添加到CompositeDisposable中,这不会触发。 我无法找到解决此问题的方法,任何线索都将不胜感激。

1 个答案:

答案 0 :(得分:0)

在登录片段中初始化CompositeDisposable并将所有disposable添加到CompositeDisposable并清除onPause。看起来像:

private var subscriptions: CompositeDisposable = CompositeDisposable()

private fun validateForm() {
    val emailObservable = viewBinding.detUserName.editText.textChangeEvents()
        .skipInitialValue()
        .map { isValidEmail(it.text) || isValidPhoneNumber(it.text) }
        .doOnDispose {
            Log.i("disposed", "emailObservable")
        }


    val passwordObservable = viewBinding.detPassword.editText.textChangeEvents()
        .skipInitialValue()
        .map { !TextUtils.isEmpty(it.text) }
        .doOnDispose {
            Log.i("disposed", "passwordObservable")
        }

    val disposable = Observable.combineLatest(emailObservable, passwordObservable,
        BiFunction<Boolean, Boolean, Boolean> { t1, t2 -> t1 && t2 }).subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe {
            viewBinding.bLogin.isEnabled = it
        }
    subscriptions.add(emailObservable, passwordObservable, disposable)
}

override fun onResume() {
    super.onResume()
    validateForm()
}

override fun onPause() {
    subscriptions.clear()
    super.onPause()
}