英文:
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 EditText
s 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<Boolean>(false)}
val editText2 by lazy { MutableLiveData<Boolean>(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 ->
binding.phoneAuthBtn.isEnabled = viewModel.editText1.value && 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(
"first" to false,
"second" to false,
)
}
to
init {
_phoneFillCheck.value = hashMapOf(
"first" to false,
"second" 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
提供与addTextChangedListener
的onTextChanged
相同的功能,而无需覆盖其他两个方法。
英文:
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
insteadobserverForever
observe
take additional parameter ofviewLifecycleOwner
, so livedata can avoid trigger the callback when activity/fragment no longer in active state, thus avoiding memory leak -
use
doOnTextChanged
instead ofaddTextChangedListener
doOnTextChanged
provide the same functionality withaddTextChangedListener#onTextChanged
without overriding the other 2 method
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论