この前、Kotlin Android Extensions
を使って感動してたら、友達から、DataBinding
使うのが昨今のAndroidプロジェクトでは一般的と教わったので、使ってみます。
環境
Android Studio 3.1.2
DataBindingとは
ViewModel
を作っておいて、そこの値を変えれば、xml
上のプロパティに自動でアクセスしてくれるものらしい。Activity
に、View
へのアクセスをごちゃごちゃ書かなくてスッキリ管理しやすくなる模様。逆にプロパティが変わったらViewModel
の値を変えるということもできるらしい。
簡単なサンプルを作ってみる
今回は、View
であるTextView
のtext
と、ViewModel
のname
を紐付けしてみたいと思います。
MyAppA
という名前でプロジェクトを作ったら、build.gradle
に2箇所追加します。
apply plugin: 'kotlin-kapt' // ここを追記
android {
...
// ここを追記
dataBinding {
enabled = true
}
}
続いて、viewmodelフォルダを作成し、その中に MainViewModel
クラスを作成。
package com.funeasysoft.myappa.viewmodel
class MainViewModel {
var name = "funeasy"
}
紐づけるxmlファイルを編集。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.funeasysoft.myappa.viewmodel.MainViewModel" />
</data>
<android.support.constraint.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.name}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</layout>
元々のLayoutを、<Layout>
で囲み、<data>
を追加し、ViewModelクラスを指定している。また、今回はTextView
のtext
とdataBindingするために、android:text="@{viewModel.name}"
とします。
ここで注意が必要で、元々ConstraintLayout
に付いている
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
は、消しておかないといけない。
消さないと以下のようなエラーになってしまう。
error: duplicate attribute.
Message{kind=ERROR, text=error: duplicate attribute., sources=[/Users/masa/DevAndroid/MyAppA/app/src/main/res/layout/activity_main.xml:13], original message=, tool name=Optional.of(AAPT)}
最後にActivity
へ、関連付けします。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setContentView(R.layout.activity_main) // コメントアウト
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
binding.viewModel = MainViewModel()
}
実行すると、画面に、 MainViewModel
クラスの name
に入れた funeasy
が表示されました。
ボタンをクリック -> TextViewを変える
buttonClicked()
を追加します。また、viewModel.name が変更されたら、表示もかわるように、ObservableField("[初期値]")
に変更します。
package com.funeasysoft.myappa.viewmodel
import android.databinding.ObservableField
class MainViewModel {
var name = ObservableField("funeasy")
fun buttonClicked() {
name.set("Button clicked!")
}
}
Button
を追加、android:onClick="@{() -> viewModel.buttonClicked()}"
を設定しておく。
<?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">
<data>
<variable
name="viewModel"
type="com.funeasysoft.myappa.viewmodel.MainViewModel" />
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{viewModel.name}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Button"
android:onClick="@{() -> viewModel.buttonClicked()}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</android.support.constraint.ConstraintLayout>
</layout>
ボタンをタップすると、確かにテキストが変更されました!
今後色々とMainViewModel
をカスタムして、どれだけ楽になるのかみていこうと思います。