0

I want to update views via databinding with livedata. Lets have a look at the scenario.

Data Class

data class Movie(var name: String = "", var createdAt: String = "")

ViewModel

class MyViewModel: ViewModel(){
   var pageTitle: MutableLiveData<String>()
   var movie: MutableLiveData<Movie>()

   fun changeTitleAndMovieName()
       pageTitle.value = "Title Changed"
       movie.value.name = "Movie Name Changed"
   } 
}

XML

<layout>
    ...
    <TextView
        ...
        android:text="@{`Title: `+viewmodel.pageTitle `Name: `+viewmodel.movie.name}"/>

    <Button
        ...
        android:onClick="@{() -> viewmodel.changeTitleAndMovieName()}"/>

</layout>

What I want to do?

  • When the button is pressed, the title and the name of movie should change and reflect to the view.

What is happening now?

  • Only page title is changing because of String type LiveData.
  • Movie name is NOT being reflected in the view because of Movie type LiveData and I am changing the property of Movie type LiveData's property.

Is there any way to update Movie type LiveData to the view when any property is changed of the Movie.

I dont want to re-assign the object to the livedata e.g. viewmodel.movie.value = Movie(...)

Amir Raza
  • 2,320
  • 1
  • 23
  • 32

1 Answers1

0

I have got the answer of my question. A hint from Here

The reference link's answer is a bit long change todo. I have got a very simple solution.

Here's what I did:

Just inherit you Data Class with BaseObservable and just call the method notifyChange() after your Object's property change from anywhere.

i.e. Data Class

  data class Movie(var name: String = "", var createdAt: String = "") : BaseObservable()

ViewModel

class MyViewModel: ViewModel(){
   var pageTitle: MutableLiveData<String>()
   var movie: MutableLiveData<Movie>()

   fun changeTitleAndMovieName()
       pageTitle.value = "Title Changed"
       movie.value.name = "Movie Name Changed"

       //here is the megic
       movie.value.notifyChange()
   } 
}
Amir Raza
  • 2,320
  • 1
  • 23
  • 32
  • if it works for you that's great. However there are reasons why people wouldn't recommend this. Your view is not observing the `MutableLiveData`, but it is just observing the `BaseObservable` inside the `MutableLiveData`. Whatever observing `MutableLiveData` is still not notified. Your solution is essentially same as without having `LiveData` at all, just put `var movie: Movie` in `ViewModel` and it will still work. – Sanlok Lee Jun 25 '19 at 20:22
  • Also, wrapping an observable with another observable is an anti-pattern. As I already mentioned in above comment, sometimes inner observable fires notifications, while outer observable does not, and vice versa. – Sanlok Lee Jun 25 '19 at 20:25
  • So how do you suggest the best way to update/notify views on changing of Object's property while using LiveData. **P.S. Do not re-assign the object.** @SanlokLee – Amir Raza Jun 27 '19 at 16:27
  • I would recommend re-assigning the object. In fact having a mutable data object in observer pattern is generally not recommended. I suggest changing every attribute in `Movie` to use `val` instead of `var`. – Sanlok Lee Jun 27 '19 at 18:36
  • If you must use mutable object, then I suggest just exposing the movie name with `movieName: MutableLiveData()` and then manually update your `movie` and `movieName` object. – Sanlok Lee Jun 27 '19 at 18:37