前提
基礎編の続きとして、Observable Objectを用いたバインドをKotlinで書いてみます。
すでにGradleの設定が済んでおり、Kotlinでバインドができるようになっていることが前提です。
モデルを作成する
シンプルなモデルを作成
今回はObservable Objectの例なのでData Classではなく、普通のクラスを使います。これはObservable Objectを用いる場合は他クラスの継承や、アノテーションを付ける必要があるためです。
とりあえずモデルはシンプルに以下のような感じです。
class OrderViewModel(val book: Book) {
val orderedBook: Book = book
var count: Int = 0 // あとで変更するので、 var で定義
}
なお、Bookクラスなどは基礎編のものを流用しています。
BaseObservableを継承する
このままではObservableにはなりませんので、BaseObservable
を継承します。
class OrderViewModel(val book: Book): BaseObservable() {
val orderedBook: Book = book
var count: Int = 0
}
変更の通知を行うための設定をする
ここがキモとなります。
行うべきことは、以下の2点です。
- プロパティのゲッターにBindableアノテーションの付与
- セッターで変更の通知を行う
これらは公式のData Binding Libraryのドキュメントにある下記の記述がソースです。
This is done by assigning a Bindable annotation to the getter and notifying in the setter.
今回はカウント(count)をObserveするために以下のようになります。
アノテーションの付け方やセッターの実装がKotlin特有ですが、ドキュメントを見れば理解できます。ページ下部の参考にリンクを置いておきます。
なお下記コードでBR
を使っていますが、これは自動で作られます。
class OrderViewModel(val book: Book): BaseObservable() {
val orderedBook: Book = book
@get:Bindable
var count: Int = 0
set(value) {
field = value // 値をセット
notifyPropertyChanged(BR.count) // 変更を通知
}
}
これでモデル側の実装は完了です。
レイアウトファイルでバインドを指示する
これはこれまで通りです。今回はcount
をバインドします。
アクティビィとレイアウトは以下のようになります。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// バインドするデータを作成。今回は手で作成
val author1 = Author(name = "一郎")
val author2 = Author(name = "次郎")
val book = Book(title = "とても良い本", price = 1000, authors = listOf(author1, author2))
var order = OrderViewModel(book)
val mainActivityBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
mainActivityBinding.order = order
}
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="order"
type="com.example.kotlinsample.viewmodel.OrderViewModel" />
</data>
...
<TextView
....
android:text="@{String.valueOf(order.count)}"
....
/>
</layout>
バインドした値を変更してみる
これで完了ですが、動作上はただのデータバインドです。
ここで、プログラムからBindableにしたcountプロパティを変更してみると、動作が確認できます。
適当にボタンを用意して、クリックでcountの値を増減させます。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// バインドするデータを作成。今回は手で作成
val author1 = Author(name = "一郎")
val author2 = Author(name = "次郎")
val book = Book(title = "とても良い本", price = 1000, authors = listOf(author1, author2))
var order = OrderViewModel(book)
val mainActivityBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
mainActivityBinding.order = order
// プラスとマイナスボタンは適宜用意し、それぞれのクリックでcountを増減させる
(findViewById(R.id.plusButton) as Button).setOnClickListener { v ->
order.count += 1
}
(findViewById(R.id.minusButton) as Button).setOnClickListener { v ->
order.count -= 1
}
}
これで実行すると、プラスとマイナスのそれぞれのボタンのクリックで、カウントのラベルが増減することが確認できます。