概要
AndroidのDataBindingやViewModelの実装について手続き的な面でつまづいたことがあったので自分なりにまとめました!
「とにかく動かすための手続きが知りたい」という方に向けてサンプルコードを具体的に記述します。
作るもの
ボタンのタップによって画像の表示⇔非表示がトグルするやつを作ります!
作りましょう
プロジェクトを作ろう
登場人物
プロジェクトを作ったらこの人達をいじっていきます!
- build.gradle(app)
- MainViewModel.kt
- MainActivity.kt
- layout/activity_main.xml
build.gradle(app)
dataBinding{ enabled = true }
をいい感じの場所に追加します!
MainViewModel.kt
android.arch.lifecycle.ViewModelを継承したMainViewModelを新規作成します!
こいつにデータ(今回だとフラグ)を保持させます。
toggle()
が呼び出される度に_flag.value
がtrue⇔falseと切り替わるイメージです。
class MainViewModel : ViewModel() {
private val _flag = MutableLiveData<Boolean>().apply {
value = false
}
val flag: LiveData<Boolean>
get() = _flag
fun toggle() {
_flag.postValue(!(flag.value ?: false))
}
}
activity_main.xml
レイアウトファイルと、ついでにstringsファイルを弄ります!
バインディングされたオブジェクトのgetterは勝手に剥いてくれるので、三項演算子の部分はviewModel.flag
と書いています。
(viewModel.getFlag().getValue()
でも動きます)
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.rodentia6.sampledatabinding.MainViewModel"/>
<import type="android.view.View"/>
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{viewModel.flag ? View.VISIBLE : View.GONE}"
app:srcCompat="@android:drawable/star_on"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/button"
app:layout_constraintLeft_toLeftOf="parent"
android:contentDescription="@null"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="80dp"
android:text="@{viewModel.flag ? @string/kesu : @string/tukeru}"
android:onClick="@{(v) -> viewModel.toggle()}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
</layout>
<resources>
<string name="app_name">SampleDataBinding</string>
<string name="tukeru">つける</string>
<string name="kesu">けす</string>
</resources>
一旦リビルドをかける
DataBindingのクラスを自動生成してもらうために一旦リビルトします!(上メニューから Build > Rebuild Project)
何かが間違っていた場合はこの時点でエラーが発生します。
MainActivity.kt
Activityのクラスを編集します!
ViewModelオブジェクトとDataBindingオブジェクトを作成して色々紐づけます。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// ViewModelオブジェクトを生成する
val viewModelFactory: ViewModelProvider.Factory = ViewModelProvider.NewInstanceFactory()
val viewModelProvider = ViewModelProvider(this, viewModelFactory)
val viewModel: MainViewModel = viewModelProvider.get(MainViewModel::class.java)
// 上記3行のコードは、build.gradle(app)にimplementation 'android.arch.lifecycle:extensions:1.1.1'を追加すると下記で代替できるようになる
// val viewModel: MainViewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
// Bindingオブジェクトを生成する
val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
// 色々紐付ける
binding.viewModel = viewModel
binding.lifecycleOwner = this
}
}
完成!
おめでとうございます、完成です!起動して触ってみましょう!
画面を回転してもフラグの状態が維持されていることがわかりますね。