仅在单击按钮时更改livedata的值。但是,即使在Kotlin Android中的片段上,观察者也被命名
我的ViewModel中有一个Livedata: -
private val _toastMessage = MutableLiveData<Long>()
val toastMessage
get() = _toastMessage
这是我更改其价值的唯一方法(单击片段中的提交按钮): -
fun onSubmitClicked(<params>){
Log.i(LOG_TAG, "submit button clicked")
uiScope.launch {
if(!myChecksForEditTextValuesSucceeded())
{
_toastMessage.value = 0
}else{
_toastMessage.value = 1
}
}
}
在片段中,我有一个观察者,为此livedata: -
transactionViewModel.toastMessage.observe(viewLifecycleOwner, Observer { it->
when{
(it.compareTo(0) == 0) -> Toast.makeText(context, resources.getString(R.string.toast_msg_transaction_not_inserted), Toast.LENGTH_SHORT).show()
else -> Toast.makeText(context, resources.getString(R.string.toast_msg_transaction_inserted), Toast.LENGTH_SHORT).show()
}
})
理想情况下,我是我的。希望只在单击我的片段上的提交按钮时,就会称呼该观察者的偏移。但是,正如我所看到的,即使在我的片段上,它也会被调用。
这可能是什么原因?
I have a LiveData in my ViewModel:-
private val _toastMessage = MutableLiveData<Long>()
val toastMessage
get() = _toastMessage
And this is the only way I am changing it's value(on click of a submit button in the fragment):-
fun onSubmitClicked(<params>){
Log.i(LOG_TAG, "submit button clicked")
uiScope.launch {
if(!myChecksForEditTextValuesSucceeded())
{
_toastMessage.value = 0
}else{
_toastMessage.value = 1
}
}
}
And in the fragment, I have an observer for this LiveData:-
transactionViewModel.toastMessage.observe(viewLifecycleOwner, Observer { it->
when{
(it.compareTo(0) == 0) -> Toast.makeText(context, resources.getString(R.string.toast_msg_transaction_not_inserted), Toast.LENGTH_SHORT).show()
else -> Toast.makeText(context, resources.getString(R.string.toast_msg_transaction_inserted), Toast.LENGTH_SHORT).show()
}
})
Ideally, I am expecting the onChange of this Observer to be called only on clicking the submit button on my fragment. But, as I can see, it is also getting called even on onCreateView of my fragment.
What could be the possible reasons for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是
livedata
在观察它时 new 值,但是当您 first 时,它也会推动最新值 观察它,或者如果观察者的生命周期
简历,并且自暂停以来数据发生了变化。因此,当您将
toastMessage
的值设置为1
时,它保持这种方式 - 和viewModel
s的寿命比fragment < /code> s(这是全部!),因此,当您的
sfragment
重新创建时,它observer
stoastMessage
,看到当前是1
,并显示敬酒。问题是您不想将其用作持久的数据状态 - 您希望它是一个单发事件,当您观察它时,您会消耗对按钮的响应。 很多解决方法,类,图书馆等
这是关于
livedata
的棘手之处之一,并且围绕使它起作用的构建有 /livedata-with-snackbar-nackativation and the-events-singleliveEvent-case-ac262673150“ rel =“ nofollow noreferrer”>旧帖子来自Android开发人员之一,与此用例讨论问题,可用的解决方法以及它们不足的地方 - 如果任何人有兴趣!但是就像它在顶部所说的那样,这一切都已经过时了,他们建议按照官方指南。官方方式基本上是:
不是处理消耗事件的唯一方法,而是他们的建议,这很简单。因此,您需要做类似的事情:
您可能还需要创建敬酒状态的枚举,而不仅仅是使用数字,更可读的方式 - 您甚至可以将其字符串ID放入枚举中:
它可以更清楚,并且与仅使用数字相比,自我记录了吗?
The issue is that
LiveData
pushes new values while you're observing it, but it also pushes the most recent value when you first observe it, or if the observer'sLifecycle
resumes and the data has changed since it was paused.So when you set
toastMessage
's value to1
, it stays that way - andViewModel
s have a longer lifetime thanFragment
s (that's the whole point!) so when yourFragment
gets recreated, itobserve
s the current value oftoastMessage
, sees that it's currently1
, and shows a Toast.The problem is you don't want to use it as a persistent data state - you want it to be a one-shot event that you consume when you observe it, so the Toast is only shown once in response to a button press. This is one of the tricky things about
LiveData
and there have been a bunch of workarounds, classes, libraries etc built around making it workThere's an old post here from one of the Android developers discussing the problem with this use case, and the workarounds available and where they fall short - in case anyone is interested! But like it says at the top, that's all outdated, and they recommend following the official guidelines.
The official way basically goes:
That's not the only way to handle consumable events, but it's what they're recommending, and it's fairly simple. So you'd want to do something like this:
You also might want to create an enum of Toast states instead of just using numbers, way more readable - you can even put their string IDs in the enum:
It can be a bit clearer and self-documenting compared to just using numbers, y'know?