I am having issues with LiveData.
I have 3 fragments A (menuFragment), B (doThingsFragment), C (displayMessageFragment). We can move from A to B, from B to C and finally from C to A.
On the onStart method of doThingsFragment, I observe LiveData From doThingsViewModel and I move to displayMessageFragment when this value changes.
doThingsViewModel :
private var _message : MutableLiveData<String> = MutableLiveData()
var message : LiveData<String> = _message
fun someFunction() {
_message.value = "blablabla"
}
doThingsFragment :
override fun onStart() {
super.onStart()
mViewModel!!.message.observe(
viewLifecycleOwner,
Observer<String>
{
msg ->
if(!msg.isNullOrEmpty() && mViewModel!!.toastType.value != null){
val args = Bundle()
args.putString("message", msg)
Navigation.findNavController(requireView()).navigate(R.id.mountUnmountValidationFragment, args)
}
})
}
It works great the first time I update _message (we go from B to C as expected). However, when I try to move from A to B again, we go into doThingsFragment observer callback again and I move on to fragment C before fragment B is even displayed.
Since _message value has not changed, I expect not to trigger the observer callback everytime doThingFragment.onStart method is called...
What am I missing ?
Thanks a lot !
LiveData
works on an Observer pattern, where something registers as an observer, and every time the thing it's observing changes, it gets notified. It's worth reading the docs on this:These are the important points - when you register to
observe
the data, you'll immediately be notified of the most recent value (if there is one), not just when there's a change. So you can't rely on that callback triggering as a signal that you need to move fromB
toC
.What you actually need to do depends on your app logic, how you can tell the difference between "fragment B just displayed, here's a value, and now I need to show fragment C" and "fragment B just displayed, here's a value, but I happen to know I don't need to show fragment C this time". You could do things with setting an
initialised
flag the first time you receive some data (might need to persist that state inonSaveInstanceState
) or holding the last-seen value (harder to persist) but you get the idea