mutablelivedata livedata example data and android observable android-livedata android-viewmodel

android - example - Actualización de LiveData en cambio de campo de objeto



mutablelivedata (3)

Estoy usando la arquitectura MVVM de Android con LiveData. Tengo un objeto como este

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; } }

Y mi modelo de vista se ve así

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 "); } }

¿Cómo puedo asegurarme de que cuando se notifique a algunos observadores de cambios de objeto de usuario? Por cierto, es importante para mí mantener estos datos en el objeto separado y no usar valores primarios como cadenas en mi ViewModel.


Al usar MVVM y LiveData, puede volver a enlazar el objeto con el diseño para que active todos los cambios en la interfaz de usuario.

Dado "usuario" es un MutableLiveData<User> MutableLiveData en el 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() } }

Archivo de actividad / fragmento:

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 })

Su archivo de diseño no debe cambiar:

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


No creo que haya ninguna mejor práctica recomendada por android para esto. Le sugeriría que utilice el método que utiliza un código más limpio y menos repetitivo.

Si está utilizando el enlace de datos de Android junto con LiveData , puede LiveData el siguiente enfoque:

Tu objeto POJO se vería así

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); } }

Por lo tanto, ya estarías teniendo una clase que notifica cada vez que cambia su propiedad. Por lo tanto, solo puede hacer uso de esta devolución de llamada de cambio de propiedad en su MutableLiveData para notificar a su observador. Puede crear un MutableLiveData personalizado para esto

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()); } }; }

Entonces todo lo que necesita hacer es usar este CustomMutableLiveData en lugar de MutableLiveData en su modelo de vista

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

De este modo, puede notificar tanto a view como a LiveData Observer con pocos cambios en el código existente. Espero eso ayude


Para que su observador reciba una notificación, debe usar setValue si hace esto user.getValue().setFirstName(user.getValue().getFirstName() + " A "); ¡Su observador no será notificado!

Ver modelo

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

Actividad / Fragmento

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

En algún lugar de tu actividad / fragmento

Esto activará el observador:

mModel.getUser().setValue(user);

Si desea actualizar solo un campo de un objeto en lugar de actualizar todo el objeto, debe tener múltiplos 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 });