簡単なサンプルですがメモとして残します。
KotlinでData Bindingのカスタムセッターを使う例です。
カスタムセッターとは
これを用いるとレイアウトへの値のバインドをセッターを通じて行うことができます。
セッターはプログラムで書くので、プログラム内で複雑な処理を行い、その結果をバインドするようなことができるようになります。
カスタムセッターに使われるメソッドを定義する
ポイントは、下記です。
- Kotlinの
object
構文を使ってシングルトンのオブジェクトを作成 -
@BindingAdapter
アノテーション以外に、@JvmStatic
も付与する -
@BindingAdapter
アノテーションの中に、任意の属性を定義する- ここで定義した属性をあとでレイアウトファイル内で用いる
- メソッドの第一引数は、カスタムセッターが使用されるViewとする
- メソッド名はなんでもよい
例えばカスタムセッターを使ってtext
プロパティに値をバインドする場合は、以下のようになります。
object CustomizedSetter{
@JvmStatic
@BindingAdapter("customAttr1", "customAttr2")
fun customizedSetterMethod(view: TextView, attr1Value: String, attr2Value: String) {
view.text = "first attr is " + attr1Value + ". second attr is " + attr2Value + "."
}
}
レイアウトから定義したカスタムセッターが呼ばれるようにする
カスタムセッターを使用するレイアウトファイルを開き、@BindingAdapter
アノテーションの引数で指定した属性にカスタムセッターに渡したい引数を記載します。
<layout ...>
<data>
<variable
name="order"
type="com.example.kotlinsample.model.Book" />
</data>
<..略..>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ここはカスタムセッター内でセットするので無視される"
customAttr1="@{String.valueOf(order.count)}"
customAttr2="@{order.book.title}"
/>
</..略..>
</layout>
実行する
実行すると定義したカスタムセッターcustomizedSetterMethod
が呼ばれ、結果が反映されます。
上記の例だと、
- カスタムセッターの第1引数は、TextView
- カスタムセッターの第2引数は、
customAttr1
の値 - カスタムセッターの第3引数は、
customAttr2
の値
として呼び出されます。
カスタムセッターないでtext
を設定しているので、レイアウト上で設定したtext
は無視されます。
なお、バインドしたモデルがBaseObservable
を実装しており、適切にプロパティの変更が通知される場合にはプロパティの変更があるたびにカスタムセッターが呼び出されます。
BaseObservableの利用についての詳細はKotlinでData Bindingをする - Observable Object編を参照してください。
Old Value と New Value
カスタムセッターのメソッドの定義によっては、これまで設定していた属性値(Old Value
と勝手にここでは呼びます)をカスタムセッターの引数から取得できます。
メソッド定義の仕方は、Old Value
の引数を先に、新しく設定された属性値を後に書きます。
たとえば、このような感じです。
object CustomizedSetter{
@JvmStatic
@BindingAdapter("customAttr1", "customAttr2")
fun customizedSetterMethod(
view: TextView,
oldAttrValue1: String?, // `customAttr1`の今までの値
oldAttrValue2: String?, // `customAttr2`の今までの値
attr1Value: String,
attr2Value: String) {
view.text = "first attr is " + attr1Value + ". second attr is " + attr2Value + "."
println(old1 + old2)
}
}
ポイントは
- Kotlinで書く場合、
Old Value
はオプショナルで受け取る必要がある- 初回に呼び出されたときは
Old Value
はnull
だから
- 初回に呼び出されたときは
- 属性の数の分、
Old Value
を先に引数として定義し、その後に新しい属性値を引数として定義する
上部のカスタムセッターと見比べれば分かりやすいと思います。