LiveDataでAndroid MVVMアーキテクチャを使用しています。このようなオブジェクトがあります
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で文字列などのプライマリ値を使用しないことが重要です。
このために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());
}
};
}
次に、ビューモデルでMutableLiveDataの代わりにこのCustomMutableLiveDataを使用するだけです。
public class InfoViewModel extends AndroidViewModel {
CustomMutableLiveData<User> user = new CustomMutableLiveData<>();
-----
-----
そのため、これを行うことで、既存のコードをほとんど変更することなく、ビューとLiveDataの両方のオブザーバーに通知できます。それが役に立てば幸い
MVVMとLiveDataを使用する場合、オブジェクトをレイアウトに再バインドして、UI上のすべての変更をトリガーできます。
「ユーザー」がViewModelのMutableLiveData<User>
である場合
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}"
/>
オブザーバーに通知するには、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);
オブジェクト全体を更新するのではなく、オブジェクトから1つのフィールドのみを更新する場合は、倍数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
});