Livedataを使用してデータバインディングを行うにはどうすればよいですか?
activity_user_detail.xml:
<data>
<variable
name="viewModel"
type="com.test.viewmodel.UserViewModel" />
</data>
<TextView
Android:id="@+id/tv_amount"
Android:layout_width="match_parent"
Android:text="@{viewModel.age}"
....
UserViewModel.Java:
public class UserViewModel extends ViewModel {
public LiveData<User> user;
public void getUserById(UserDao userDao, String userId){
transaction = UserDao .load(userId);
}
}
UserDao.Java:
@Query("SELECT * FROM `user` WHERE id = :userId")
LiveData<User> load(String userId);
UserDetailActivity.Java:
private ActivityUserDetailBinding binding;
binding = DataBindingUtil.setContentView(this, R.layout.activity_user_detail);
viewModel = ViewModelProviders.of(this).get(UserViewModel.class);
viewModel.getUserById(userDao, userId);
viewModel.user.observe(this, user -> binding.setViewModel(user)); // How to bind livedata?
私もこれを試しました:
binding.setViewModel(viewModel);
これは、LiveDataとObservableFieldの動作を理解するためのサンプルです。 TオブジェクトとsetValue()をLiveDataで、またはset(T)をObservableFieldで変更する必要があります。オブジェクトTのプロパティを変更しても、UIは更新されません。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.example.tutorial3livedata_databinding2objects.UserViewModel" />
</data>
<Android.support.constraint.ConstraintLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<TextView
Android:id="@+id/user_info"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text='@{viewModel.userMutableLiveData.name+ ", email " + viewModel.userMutableLiveData.email}'
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.1" />
<EditText
Android:id="@+id/et_name"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginEnd="8dp"
Android:layout_marginStart="8dp"
Android:layout_marginTop="48dp"
Android:text="@={viewModel.userMutableLiveData.name}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/user_info" />
<EditText
Android:id="@+id/et_email"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginEnd="8dp"
Android:layout_marginStart="8dp"
Android:layout_marginTop="28dp"
Android:text="@={viewModel.userMutableLiveData.email}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/et_name" />
<Button
Android:id="@+id/button_change_name"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginTop="32dp"
Android:onClick="@{() -> viewModel.changeUserName()}"
Android:text="Change Name"
app:layout_constraintEnd_toStartOf="@+id/button_change_user"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/et_email" />
<Button
Android:id="@+id/button_change_user"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:onClick="@{() -> viewModel.changeUser()}"
Android:text="Change User"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/button_change_name"
app:layout_constraintTop_toTopOf="@+id/button_change_name" />
<Button
Android:id="@+id/button"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginTop="56dp"
Android:text="Display User"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button_change_name" />
</Android.support.constraint.ConstraintLayout>
</layout>
ViewModel
public class UserViewModel extends ViewModel {
public MutableLiveData<User> userMutableLiveData = new MutableLiveData<>();
private User mUser;
public UserViewModel() {
mUser = new User("User", "[email protected]");
userMutableLiveData.setValue(mUser);
}
public void changeUserName() {
// Both updates LiveData but does not update UI
mUser.setName("Name is Changed");
// userMutableLiveData.getValue().setName("Updated Name");
// This one Updates UI
// userMutableLiveData.setValue(userMutableLiveData.getValue());
}
public void changeUser() {
mUser = new User("New User Name", "[email protected]");
// Without setting new value UI is not updated and observe is not called
userMutableLiveData.setValue(mUser);
}
}
主な活動
/*
Without binding.setLifecycleOwner(this), liveData.setValue() does not update UI
liveData.setValue() updates UI
EditText changes LiveData but does not update UI
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
UserViewModel userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
// LiveData should call setValue() to update UI via binding
binding.setViewModel(userViewModel);
// Required to update UI with LiveData
binding.setLifecycleOwner(this);
}
}
このコードは学習用です。
このコードから取得できる結果:
1- changeUserName()でユーザー名を変更すると、LiveDataの既存のユーザーの名前が更新されますが、UIは更新されません。デバイスを回転させると、UIが更新されます。
2- UserをLiveDataに変更すると、setValue()データバインディングが機能します。
3- EditText双方向バインディングを使用してユーザープロパティを変更するAndroid:text="@={viewModel.userMutableLiveData.name}"
LiveDataのユーザー名を変更しますが、ユーザーが同じであるため、デバイスが回転するまでUIを更新しません。