LoginSignup
2
1

More than 5 years have passed since last update.

KotlinでData Bindingをする - カスタムセッター編

Posted at

簡単なサンプルですがメモとして残します。
KotlinでData Bindingのカスタムセッターを使う例です。

カスタムセッターとは

これを用いるとレイアウトへの値のバインドをセッターを通じて行うことができます。
セッターはプログラムで書くので、プログラム内で複雑な処理を行い、その結果をバインドするようなことができるようになります。

カスタムセッターに使われるメソッドを定義する

ポイントは、下記です。

  • Kotlinのobject構文を使ってシングルトンのオブジェクトを作成
  • @BindingAdapterアノテーション以外に、@JvmStaticも付与する
  • @BindingAdapterアノテーションの中に、任意の属性を定義する
    • ここで定義した属性をあとでレイアウトファイル内で用いる
  • メソッドの第一引数は、カスタムセッターが使用されるViewとする
  • メソッド名はなんでもよい

例えばカスタムセッターを使ってtextプロパティに値をバインドする場合は、以下のようになります。

CustomizedSetter.kt
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アノテーションの引数で指定した属性にカスタムセッターに渡したい引数を記載します。

SampleLayout.kt
<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の引数を先に、新しく設定された属性値を後に書きます。

たとえば、このような感じです。

CustomizedSetter.kt
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 Valuenullだから
  • 属性の数の分、Old Valueを先に引数として定義し、その後に新しい属性値を引数として定義する

上部のカスタムセッターと見比べれば分かりやすいと思います。

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1