Kotlin: ViewModel的MutableLiveData HashMap没有被观察到

huangapple go评论56阅读模式
英文:

Kotlin: MutableLiveData HashMap of ViewModel is not observed

问题

我想实时检查两个EditText字段是否已填写。

因此,我创建了一个具有MutableLiveData<HashMap<String, Boolean>>ViewModel

class PhoneFillClass : ViewModel() {
    var _phoneFillCheck = MutableLiveData<HashMap<String, Boolean>>()
    var phoneFillCheck = _phoneFillCheck.value

    init {
        phoneFillCheck = hashMapOf(
            "first" to false,
            "second" to false,
        )
    }

    fun changePhoneFill(field: String, fill: Boolean) {
        phoneFillCheck?.set(field, fill)
    }
}

这个HashMap包含两个对象,"first"和"second",都初始化为false

如果EditText的文本长度变为4,我将使每个"first"或"second"键的值更改为true

binding.phoneInput1.addTextChangedListener(object : TextWatcher {
    override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
        //null
    }

    override fun onTextChanged(char: CharSequence?, start: Int, before: Int, count: Int) {
        if (char?.length == 4) {
            binding.errorMessage.visibility = View.GONE
            phoneTxtCheck.changePhoneFill("first", true)
        } else {
            binding.errorMessage.visibility = View.VISIBLE
            phoneTxtCheck.changePhoneFill("first", false)
        }
    }

    override fun afterTextChanged(p0: Editable?) {
        // null
    }
})

像上面这样,phoneTxtCheck.changePhoneFill("first", true)这一行会更改MutableLiveData的"first"键的值。

然后,我注册了这个ViewModel。

phoneTxtCheck._phoneFillCheck.observeForever(Observer { value ->
    Log.d("9th", "$value")
    binding.phoneAuthBtn.isEnabled = (value["first"] == true && value["second"] == true)
})

这样,如果"first"和"second"的值都变为true,我将启用按钮。

但它不起作用,当我从observeForever中记录value时,什么都不打印。

我对Kotlin中的MutableLiveData和ViewModel不太熟悉,请告诉我代码中哪一部分是错误的。

谢谢!

英文:

I want to check 2 EditText fields are filled or not in real time.

So I created ViewModel which has MutableLiveData<HashMap<String, Boolean>>.

class PhoneFillClass : ViewModel() {
    var _phoneFillCheck = MutableLiveData<HashMap<String, Boolean>>()
    var phoneFillCheck = _phoneFillCheck.value
init {
    phoneFillCheck = hashMapOf(
        "first" to false,
        "second" to false,
    )
}

fun changePhoneFill(field: String, fill: Boolean) {
    phoneFillCheck?.set(field, fill)

   }
}

This hasMap has two objects in map, first and second.
And Both are initiated as false.

If EditTexts text length becomes 4, I will make each first or second key's value changed to true.

 binding.phoneInput1.addTextChangedListener(object : TextWatcher {

        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            //null
        }

        override fun onTextChanged(char: CharSequence?, start: Int, before: Int, count: Int) {

            if (char?.length == 4) {
                binding.errorMessage.visibility = View.GONE
                phoneTxtCheck.changePhoneFill("first", true)
            } else {
                binding.errorMessage.visibility = View.VISIBLE
                phoneTxtCheck.changePhoneFill("first", false)
            }
        }

            override fun afterTextChanged(p0: Editable?) {
        // null
    }
})

Like above, phoneTxtCheck.changePhoneFill("first", true) this line changes value of first key of MutableLiveData.

And I register this ViewModel.

    phoneTxtCheck._phoneFillCheck.observeForever(Observer { value ->
        Log.d("9th", "$value")
        binding.phoneAuthBtn.isEnabled = (value["first"] == true && value["second"] == true)
    })

So that if both of "first" and "second" 's values become true, I will enable Button.

But It doesn't work and when I Log value from observeForever, It prints nothing.

I'm not familiar with MutableLiveData and ViewModel in Kotlin, Please let me know which part is wrong in my code.

Thank you!

答案1

得分: 0

您可以创建两个可变的LiveData对象,根据需要进行观察。
在ViewModel中创建两个对象。

val editText1 by lazy { MutableLiveData<Boolean>(false) }
val editText2 by lazy { MutableLiveData<Boolean>(false) }

在活动中,当满足您的editText条件时更新值。

viewModel.editText1.value = true

观察可变的LiveData的更改。

viewModel.editText1.observe(this@ActivityName) { value ->
    binding.phoneAuthBtn.isEnabled = viewModel.editText1.value && viewModel.editText2.value
}
英文:

You can create two mutable live data object can observe according to use.
>in ViewModel create two object.

val editText1 by lazy { MutableLiveData&lt;Boolean&gt;(false)}
val editText2 by lazy { MutableLiveData&lt;Boolean&gt;(false)}

> in activity update the value when your editText condition satisfied

viewModel.editText1.value = true

> Observe the changes in the mutableLiveData

viewModel.editText1.observe( this@ActivityName ){ value -&gt;
    binding.phoneAuthBtn.isEnabled = viewModel.editText1.value &amp;&amp; viewModel.editText2.value
}

答案2

得分: 0

更改

init {
    phoneFillCheck = hashMapOf(
        "first" to false,
        "second" to false,
    )
}

init {
    _phoneFillCheck.value = hashMapOf(
        "first" to false,
        "second" to false,
    )
}

并观察 phoneFillCheck

英文:

Change

init {
    phoneFillCheck = hashMapOf(
        &quot;first&quot; to false,
        &quot;second&quot; to false,
    )
}

to

init {
    _phoneFillCheck.value = hashMapOf(
        &quot;first&quot; to false,
        &quot;second&quot; to false,
    )
}

and observe phoneFillCheck.

答案3

得分: 0

LiveData在LiveData内部的值发生变化时会触发观察者方法。

您可以将您的代码更改为类似以下方式:

fun changePhoneFill(field: String, fill: Boolean) {
    phoneFillCheck?.set(field, fill)
    _phoneFillCheck.value = phoneFillCheck
}

此外,您提供的部分代码可以进行改进,例如:

  • 使用 observe 而不是 observerForever

    observe 接受额外的参数 viewLifecycleOwner,因此 LiveData 可以避免在活动/片段不再处于活动状态时触发回调,从而避免内存泄漏。

  • 使用 doOnTextChanged 而不是 addTextChangedListener

    doOnTextChanged 提供与 addTextChangedListeneronTextChanged 相同的功能,而无需覆盖其他两个方法。

英文:

Livedata will trigger the observer method when value inside the livedata is changed

you can change your code into something like this

fun changePhoneFill(field: String, fill: Boolean) {
    phoneFillCheck?.set(field, fill)
    _phoneFillCheck.value = phoneFillCheck
   }
}

also, there is few of the code you provided can be improved, such as :

  • use observe instead observerForever

    observe take additional parameter of viewLifecycleOwner, so livedata can avoid trigger the callback when activity/fragment no longer in active state, thus avoiding memory leak

  • use doOnTextChanged instead of addTextChangedListener

    doOnTextChanged provide the same functionality with addTextChangedListener#onTextChanged without overriding the other 2 method

huangapple
  • 本文由 发表于 2023年1月9日 13:08:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75053387.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定