Androidプログラミング-DataBinding¶
概要¶
2010年代中頃までのAndroidのアプリケーション構造は、ビューとなるレイアウトXML、コントローラとなるActivity/Fragment、モデルとなる任意のクラス(POJOまたはContentProvider)から構成されていました。画面に表示する内容(文字列、画像、等)は、コントローラが仲立ちし、モデルのデータ構造を文字列等に変換し適切なビューに設定することで実現していました。モデルのデータの変更はオブザーバパターンを作り込み、コントローラで検出してビューに反映していました。このため、コントローラが肥大化する傾向が高く俗にファットコントローラというアンチパターンに陥りがちです。
そこで、モデルとビューを直結し、モデルのデータをビュー側で表示形式に変換し、またデータの変更も自動で反映(LiveDataを中継することで)できるようにしたものが DataBindingです。
コントローラがすることは、データバインディングの初期化とビュー側で参照するモデルの設定だけになります。
ざっと使い方メモ¶
レイアウトXMLのDataBinding対応¶
レイアウトXMLのルート要素をlayoutとする¶
<?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"
xmlns:tools="http://schemas.android.com/tools">
:(中略)
</layout>
参照したいデータ(インスタンス)を定義する¶
<layout ...>
<data>
<variable
name="viewModel"
type="com.torutk.android.temprecorder.jetpackkt.MainViewModel" />
</data>
</layout>
- ルート要素layoutの子要素にdata要素を定義、その子要素にvariable要素を定義
- variable要素のname属性は、レイアウトXMLの中で参照するときのインスタンス名(任意の名前で可)
ActivityにてBindingの生成と参照するデータの設定¶
class MainActivity : AppCompatActivity() {
private val temperatureViewModel: MainViewModel by viewModels { MainViewModel.Factory(this.application) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main) // (1)
binding.lifecycleOwner = this // (2)
binding.viewModel = temperatureViewModel // (3)
- (1) コンパイル時に、DataBinding定義を持つレイアウトXML(ここではactivity_main.xml)の拡張子を除いた名前(activity_main)をパスカル形式に変換して(ActivityMain)末尾にBindingを追加した名前(ActivityMainBinding)のクラスが自動生成されます。
このクラスのインスタンスは、DataBindingUtilのsetContentViewメソッドを呼び生成します。 - (2) LiveDataを使う際にデータの更新を自動的に反映させるためにはlifecycleOwnerをセットします。
- (3) レイアウトXMLで参照するデータを設定します。バインディングのプロパティ名は、variable要素のname属性です。
bindingをローカル変数ではなくプロパティにする場合¶
onCreateメソッド以外でbindingを使用したい場合は、bindingをプロパティとします。
class MainActivity : AppCompatActivity() {
private val binding: ActivityMainBinding by lazy {
DataBindingUtil.setContentView(this, R.layout.activity_main)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.lifecycleOwner = this
ビューの表示設定¶
属性プロパティ形式¶
variable要素の名前から辿れるプロパティを表示に使うことができます。@{} 構文で属性プロパティ形式で記述します。
<TextView
:
android:text="@{viewModel.submitTitle}"
/>
android:text属性はString型なので、String型を戻り値型とするviewModelのgetSubmitTitle()メソッド、あるいは submitTitle()メソッドを呼び、その結果を設定します。ただしメソッドの戻り値型がString型でない場合はTextViewのtext属性に設定できないため、変換が必要となります。
式言語¶
DataBindingではXMLファイル中に「式言語」でデータ参照を記述します。先の属性プロパティ形式は式言語の一つの形式です。
式言語では、Javaのコードを呼び出すことができます。
<TextView
:
android:text="@{String.valueOf(viewModel.index + 1)}"
/>
他のビューの参照、リソースの参照なども可能です。
他のビューの属性を参照するときは、式言語中にビューのID名をキャメルケースにした名称を使用します。
イベントの対応付け(ボタン押下時の処理)¶
<Button
:
android:onClick="@{() -> viewModel.incrementMeasurementAt(10)}"
/>
ボタン押下時に、ラムダ式でviewModelのincrementMeasurementAtメソッドを呼び出します。