Обновление LiveData при изменении поля объекта
Я использую архитектуру Android MVVM с LiveData. У меня есть такой объект
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;
}
}
и моя модель выглядит так
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 ");
}
}
Как я могу убедиться, что когда некоторые поданные в объект пользователя изменения наблюдателей получить уведомление? Кстати, мне важно сохранить эти данные в отдельном объекте и не использовать первичные значения, такие как строки в моей ViewModel.
3 ответов
Я не думаю, что есть какая-либо лучшая практика, как таковая, рекомендованная android для этого. Я бы предложил вам использовать подход, который использует более чистый и менее шаблонный код.
если вы используете привязку данных android вместе с LiveData
вы можете пойти со следующим подходом:
ваш объект POJO будет выглядеть примерно так
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);
}
}
таким образом, у вас уже будет класс, который уведомляет, когда его свойство изменяется. Так что вы можете просто использовать это свойство изменяет обратный вызов в MutableLiveData, чтобы уведомить своего наблюдателя. Вы можете создать пользовательский MutableLiveData для этого
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());
}
};
}
тогда все, что вам нужно сделать, это использовать этот CustomMutableLiveData вместо MutableLiveData в вашей модели представления
public class InfoViewModel extends AndroidViewModel {
CustomMutableLiveData<User> user = new CustomMutableLiveData<>();
-----
-----
таким образом, делая это, вы можете уведомить как view & LiveData observer с небольшим изменением существующего кода. Надеюсь, это поможет
для вашего наблюдателя получить уведомление вы должны использовать setValue
если вы сделаете это
user.getValue().setFirstName(user.getValue().getFirstName() + " A ");
ваш обозреватель не будет !
Посмотреть Модель
public MutableLiveData<User> getUser() {
return user;
}
Активность / Фрагмент
mModel = ViewModelProviders.of(this).get(InfoViewModel.class);
mModel.getUser().observe(this, s -> {
// User has been modified
});
где-то в вашей деятельности / фрагмент
это вызовет наблюдатель :
mModel.getUser().setValue(user);
если вы хотите обновить только одно поле из объекта вместо обновления всего объекта, у вас должно быть несколько 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
});
при использовании MVVM и LiveData вы можете повторно привязать объект к макету, чтобы он инициировал все изменения в пользовательском интерфейсе.
данный "пользователь" является MutableLiveData<User>
в 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()
}
}
активность/фрагмент файл:
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
})
ваш файл макета не должен меняться:
<data>
<variable
name="user"
type="com.project.model.User" />
</data>
...
<TextView
android:id="@+id/firstname"
android:text="@{user.firstname}"
/>