Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LiveData update on object field change

I'm using Android MVVM architecture with LiveData. I have an object like this

public class User {     private String firstName;     private String lastName;      public String getFirstName() {         return firstName;     }      public void setFirstName(String firstName) {         this.firstName = firstName;     }      public String getLastName() {         return lastName;     }      public void setLastName(String lastName) {         this.lastName = lastName;     } } 

And my view model looks like this

public class InfoViewModel extends AndroidViewModel {     MutableLiveData<User> user = new MutableLiveData<>();      public InfoViewModel(@NonNull Application application) {         super(application);         User user = new User();         user.setFirstName("Alireza");         user.setLastName("Ahmadi");          this.user.setValue(user);     }      public LiveData<User> getUser(){         return user;     }      public void change(){         user.getValue().setFirstName(user.getValue().getFirstName() + " A ");     } } 

How can I make sure when some field in user object changes observers get notified? BTW it is important to me to keep this data in the separate object and not use primary values like Strings in my ViewModel.

like image 208
Alireza A. Ahmadi Avatar asked Dec 29 '17 09:12

Alireza A. Ahmadi


People also ask

How do I update my LiveData?

To update the LiveData object you have to use MutableLivedata class, because LiveData has no publicly available methods to update the stored data. The MutableLiveData class has the setValue(T) and postValue(T) methods publicly and you must use these if you need to edit the value stored in a LiveData object.

What is the difference between setValue and postValue in LiveData?

The setValue is a class that holds observable data. Live data is lifecycle-aware. postValue() is not lifecycle aware. The value will be updated whenever the main thread runs.

What is the difference between MutableLiveData and LiveData?

The only key difference between LiveData and MutableLiveData is that you can change the value of MutableLiveData but LiveData does not allow you to change it's value.

Is LiveData lifecycle aware?

LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services.


2 Answers

I don't think there is any best practice as such recommended by android for this. I would suggest you to use the approach which uses cleaner & less boilerplate code.

If you are using android data binding along with LiveData you can go with the following approach:

Your POJO object would look something like this

public class User extends BaseObservable {     private String firstName;     private String lastName;      @Bindable     public String getFirstName() {         return firstName;     }      public void setFirstName(String firstName) {         this.firstName = firstName;         notifyPropertyChanged(BR.firstName);     }      @Bindable     public String getLastName() {         return lastName;     }      public void setLastName(String lastName) {         this.lastName = lastName;         notifyPropertyChanged(BR.lastName);     } } 

So you would be already having a class which notifies whenever its property changes. So you can just make use of this property change callback in your MutableLiveData to notify its observer. You can create a custom MutableLiveData for this

public class CustomMutableLiveData<T extends BaseObservable>         extends MutableLiveData<T> {       @Override     public void setValue(T value) {         super.setValue(value);          //listen to property changes         value.addOnPropertyChangedCallback(callback);     }      Observable.OnPropertyChangedCallback callback = new Observable.OnPropertyChangedCallback() {         @Override         public void onPropertyChanged(Observable sender, int propertyId) {              //Trigger LiveData observer on change of any property in object             setValue(getValue());          }     };   } 

Then all you need to do is use this CustomMutableLiveData instead of MutableLiveData in your View Model

public class InfoViewModel extends AndroidViewModel {      CustomMutableLiveData<User> user = new CustomMutableLiveData<>(); ----- ----- 

So by doing this you can notify both view & LiveData observer with little change to existing code. Hope it helps

like image 180
Abhishek V Avatar answered Sep 17 '22 10:09

Abhishek V


When using MVVM and LiveData, you can re-bind the object to the layout so it will trigger all changes on the UI.

Given "user" is a MutableLiveData<User> in the ViewModel

ViewModel

class SampleViewModel : ViewModel() {     val user = MutableLiveData<User>()      fun onChange() {         user.value.firstname = "New name"         user.value = user.value // force postValue to notify Observers         // can also use user.postValue()     } } 

Activity/Fragment file:

viewModel = ViewModelProviders             .of(this)             .get(SampleViewModel::class.java)  // when viewModel.user changes, this observer get notified and re-bind // the user model with the layout. viewModel.user.observe(this, Observer {     binding.user = it //<- re-binding user }) 

Your layout file shouldn't change:

<data>     <variable         name="user"         type="com.project.model.User" /> </data>  ...  <TextView         android:id="@+id/firstname"         android:text="@{user.firstname}"         /> 
like image 30
sonique Avatar answered Sep 19 '22 10:09

sonique