AndroidX ライブラリに含まれているアーキテクチャ コンポーネントを使用することで、堅牢でテストとメンテナンスが簡単なアプリを設計できます。データ バインディング ライブラリはアーキテクチャ コンポーネントとシームレスに連携し、UI の開発をさらに簡素化します。アプリのレイアウトはアーキテクチャ コンポーネントのデータにバインドできます。この機能は、UI コントローラのライフサイクルを管理し、データの変更について通知するのに役立っています。
このページでは、アーキテクチャ コンポーネントをアプリに組み込んで、データ バインディング ライブラリを使用するメリットをさらに拡大する方法を説明します。
LiveData を使用してデータの変更について UI に通知する
LiveData
オブジェクトをデータ バインディング ソースとして使用することで、データの変更について UI に自動的に通知できます。このアーキテクチャ コンポーネントについて詳しくは、LiveData の概要をご覧ください。
LiveData
オブジェクトは、Observable
を実装するオブジェクト(監視可能なフィールドなど)とは異なり、データの変更に関する情報を受信するオブザーバーのライフサイクルを認識しています。この情報にはさまざまな利点があります。詳しくは、LiveData を使用するメリットをご覧ください。Android Studio バージョン 3.1 以降では、データ バインディング コードにおいて監視可能なフィールドを LiveData
オブジェクトに置き換えることができます。
LiveData
オブジェクトをバインディング クラスとともに使用するには、ライフサイクル所有者を指定して LiveData
オブジェクトのスコープを定義する必要があります。次の例では、バインディング クラスをインスタンス化した後にアクティビティをライフサイクル所有者として指定しています。
Kotlin
class ViewModelActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { // Inflate view and obtain an instance of the binding class. val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user) // Specify the current activity as the lifecycle owner. binding.setLifecycleOwner(this) } }
Java
class ViewModelActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { // Inflate view and obtain an instance of the binding class. UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user); // Specify the current activity as the lifecycle owner. binding.setLifecycleOwner(this); } }
ViewModel を使用して UI 関連のデータを管理するで説明するように、ViewModel
コンポーネントを使用してデータをレイアウトにバインドできます。ViewModel
コンポーネントで LiveData
オブジェクトを使用すると、データを変換したり、複数のデータソースを統合したりできます。次の例は、ViewModel
のデータを変換する方法を示しています。
Kotlin
class ScheduleViewModel : ViewModel() { val userName: LiveDatainit { val result = Repository.userName userName = Transformations.map(result) { result -> result.value } } }
Java
class ScheduleViewModel extends ViewModel { LiveDatausername; public ScheduleViewModel() { String result = Repository.userName; userName = Transformations.map(result, result -> result.value); } }
ViewModel を使用して UI 関連のデータを管理する
データ バインディング ライブラリは ViewModel
コンポーネントとシームレスに連携します。レイアウトは、このコンポーネントが公開するデータを監視し、その変更に反応します。ViewModel
コンポーネントをデータ バインディング ライブラリとともに使用すると、UI ロジックをレイアウトからテストが容易なコンポーネントに移動できます。また、データ バインディング ライブラリを使用すると、必要に応じてビューをデータソースにバインドしたり、そのバインドを解除したりできます。残りの作業のほとんどは、正しいデータが公開されていることを確認することです。このアーキテクチャ コンポーネントについて詳しくは、ViewModel の概要をご覧ください。
ViewModel
コンポーネントをデータ バインディング ライブラリとともに使用するには、ViewModel
クラスから継承したコンポーネントをインスタンス化し、バインディング クラスのインスタンスを取得して、ViewModel
コンポーネントをバインディング クラスのプロパティに割り当てる必要があります。次の例は、このコンポーネントとライブラリを併用する方法を示しています。
Kotlin
class ViewModelActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { // Obtain the ViewModel component. val userModel: UserModel by viewModels() // Inflate view and obtain an instance of the binding class. val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user) // Assign the component to a property in the binding class. binding.viewmodel = userModel } }
Java
class ViewModelActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { // Obtain the ViewModel component. UserModel userModel = new ViewModelProvider(this).get(UserModel.class); // Inflate view and obtain an instance of the binding class. UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user); // Assign the component to a property in the binding class. binding.viewmodel = userModel; } }
次の例に示すように、レイアウトでバインディング式を使用して、ViewModel
コンポーネントのプロパティとメソッドを対応するビューに割り当てます。
<CheckBox
android:id="@+id/rememberMeCheckBox"
android:checked="@{viewmodel.rememberMe}"
android:onCheckedChanged="@{() -> viewmodel.rememberMeChanged()}" />
監視可能な ViewModel を使用して、バインディング アダプターを詳細に管理する
Observable
を実装する ViewModel
コンポーネントを使用すると、LiveData
オブジェクトの使用方法と同様に、データの変更について他のアプリ コンポーネントに通知できます。
LiveData
のライフサイクル管理機能を失ったとしても、LiveData
オブジェクトを使用するよりも、Observable
インターフェースを実装する ViewModel
コンポーネントを使用する方が望ましい場合があります。Observable
を実装する ViewModel
コンポーネントを使用すると、バインディング アダプターをアプリで詳細に管理できるようになります。たとえばこのパターンでは、データが変更されたときの通知を詳細に管理できるほか、カスタムのメソッドを指定して、双方向データ バインディングの属性の値を設定することもできます。
監視可能な ViewModel
コンポーネントを実装するには、ViewModel
クラスから継承し、Observable
インターフェースを実装するクラスを作成する必要があります。オブザーバーが addOnPropertyChangedCallback()
メソッドと removeOnPropertyChangedCallback()
メソッドを使用して通知を登録または登録解除する場合は、カスタム ロジックを指定できます。また、notifyPropertyChanged()
メソッドのプロパティが変更されたときに実行するカスタム ロジックを指定することもできます。次のコード例は、監視可能な ViewModel
を実装する方法を示しています。
Kotlin
/** * A ViewModel that is also an Observable, * to be used with the Data Binding Library. */ open class ObservableViewModel : ViewModel(), Observable { private val callbacks: PropertyChangeRegistry = PropertyChangeRegistry() override fun addOnPropertyChangedCallback( callback: Observable.OnPropertyChangedCallback) { callbacks.add(callback) } override fun removeOnPropertyChangedCallback( callback: Observable.OnPropertyChangedCallback) { callbacks.remove(callback) } /** * Notifies observers that all properties of this instance have changed. */ fun notifyChange() { callbacks.notifyCallbacks(this, 0, null) } /** * Notifies observers that a specific property has changed. The getter for the * property that changes should be marked with the @Bindable annotation to * generate a field in the BR class to be used as the fieldId parameter. * * @param fieldId The generated BR id for the Bindable field. */ fun notifyPropertyChanged(fieldId: Int) { callbacks.notifyCallbacks(this, fieldId, null) } }
Java
/** * A ViewModel that is also an Observable, * to be used with the Data Binding Library. */ class ObservableViewModel extends ViewModel implements Observable { private PropertyChangeRegistry callbacks = new PropertyChangeRegistry(); @Override protected void addOnPropertyChangedCallback( Observable.OnPropertyChangedCallback callback) { callbacks.add(callback); } @Override protected void removeOnPropertyChangedCallback( Observable.OnPropertyChangedCallback callback) { callbacks.remove(callback); } /** * Notifies observers that all properties of this instance have changed. */ void notifyChange() { callbacks.notifyCallbacks(this, 0, null); } /** * Notifies observers that a specific property has changed. The getter for the * property that changes should be marked with the @Bindable annotation to * generate a field in the BR class to be used as the fieldId parameter. * * @param fieldId The generated BR id for the Bindable field. */ void notifyPropertyChanged(int fieldId) { callbacks.notifyCallbacks(this, fieldId, null); } }
参考情報
データ バインディングの詳細については、以下の参考情報をご確認ください。