LiveData update when object field changes

I am using Android MVVM architecture with LiveData. I have such an object

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 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 that some observer changes registered in user objects are notified? By the way, it’s important for me to store this data in a separate object and not use primary values, such as strings in my ViewModel.

+22
android observable android-livedata android-viewmodel
source share
4 answers

I don’t think there is any best practice recommended by android for this. I suggest you use an approach that uses cleaner and less boilerplate code.

If you use data binding to android files with LiveData , you can use the following approach:

Your POJO will 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 will already have a class that notifies you of every change to its property. That way, you can simply use this property change callback in your MutableLiveData to notify your 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 have to do is use this CustomMutableLiveData instead of MutableLiveData in your view model

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

Thus, by doing this, you can notify the viewer browser and LiveData with a slight change to the existing code. Hope this helps.

+27
source share

When using MVVM and LiveData, you can re-attach the object to the layout so that it causes all changes in the user interface.

This "user" is the 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 = viewModel.user //<- re-binding }) 

Your layout file should not change:

 <data> <variable name="user" type="com.project.model.User" /> </data> ... <TextView android:id="@+id/firstname" android:text="@{user.firstname}" /> 
+7
source share

For your observer to receive a notification, you must use setValue if you do this user.getValue().setFirstName(user.getValue().getFirstName() + " A "); your observer will not be notified!

View Model

 public MutableLiveData<User> getUser() { return user; } 

Activity / fragment

 mModel = ViewModelProviders.of(this).get(InfoViewModel.class); mModel.getUser().observe(this, s -> { // User has been modified }); 

Somewhere in your activity / fragment

This will trigger an observer:

 mModel.getUser().setValue(user); 

If you want to update only one field from an object instead of updating the entire object, you must have multiple MutableLiveData<String>

 // View Model private MutableLiveData<String> firstName; private MutableLiveData<String> lastName; //Somewhere in your code mModel.getFirstName().setValue(user.getValue().getFirstName() + " A "); mModel.getFirstName().observe(this, s -> { // Firstname has been modified }); 
0
source share

I sent the same question and I got the simplest solution. Find my answer here.

0
source share

All Articles