3

I am following the google android project "guess it" through udacity where they introduce livedata and mutablelivedata. We've got to the point where we're creating a livedata equivalent to a mutablelivedata object and creating a get() backingproperty for the livedata to the mutablelivedata instance. We make all changes to the data in the viewModel using the mutablelivedata instance. Our UI Fragment sets observers on the viewModel's livedata objects, NOT the mutablelivedata objects.

Dispite the observer being on the livedata instance and not the mutablelivedata instance, when the mutablelivedata object is updated, the livedata observer code is being triggered. I love that it works like this but I don't exactly understand how it works. Can anyone explain this to me?

In ViewModel

val _word = MutableLiveData<String>()
val word : LiveData<String>
        get() = _word

Edit in ViewModel

private fun nextWord() {
    //Select and remove a word from the list
    if (wordList.isEmpty()) {
        //gameFinished()
    } else {
        _word.value = wordList.removeAt(0)
    }
}

In UI Fragment

viewModel.word.observe(this, Observer{newWord ->
            binding.wordText.text = newWord
        })
misterbee180
  • 325
  • 1
  • 13

1 Answers1

6

Our UI Fragment sets observers on the viewModel's livedata objects, NOT the mutablelivedata objects.

It is the same object. _word and word both point to the MutableLiveData. However, from a data type standpoint, word is defined as a LiveData, to hide the implementation details from the fragment.

So, the observers are being placed on the same object that is getting the value updates.

Personally, I prefer to write this code as:

private val _word = MutableLiveData<String>()
val word : LiveData<String> = _word

...as IMHO that is easier to read and has the same effect.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • word and _word are not the same object initially. In fact, now that I think of it, word isn't even ever set to an object. So is it the setting of get() = _word that sets _word and word to the same object? – misterbee180 May 17 '19 at 21:40
  • @misterbee180: "word and _word are not the same object initially" -- yes, they are. They are different *properties*, but they refer to the same object. "word isn't even ever set to an object" -- it is a property that has delegated its `get()` accessor to another property. So, when you reference `word`, you are really getting `_word`, and so they are the same object. "So is it the setting of get() = _word that sets _word and word to the same object?" -- I would not use "setting" as the verb, but otherwise yes. See my updated answer for alternative syntax. – CommonsWare May 17 '19 at 21:45
  • GOTCHA! Funny enough I was literally about to ask whether val word : LiveData = _word was equivalent to what I had so I'm glad you read my mind. – misterbee180 May 17 '19 at 21:48
  • In fact, I totally understand now that you've said that. It's not just when we access the value that the object associated w/ _word gets passed but also when we access word to set the observer on the object. By setting the get() function to return _word, it calls .observe on the object associated w/ _word. Thank You! – misterbee180 May 17 '19 at 21:51