ViewModelでの単方向・双方向データバインディング
こんにちは。
Androidを実装してて、ViewModelの単方向データバインディングと双方向データバインディングとでどう実装方法が違ったっけなっていうことが結構あったので、それの忘備録になります。
単方向・双方向データバインディングとは
まず、言葉の意味を見てみましょう。
まさに、文字の意味通りですね。
では、ViewModelのデータバインディングでいうと
単方向データバインディング
ViewModelの値変更 -> Viewへ反映双方向データバインディング
ViewModelの値変更 -> Viewへ反映
Viewの値変更 -> ViewModelへ反映
このような形になります。
EditTextでいうと、単方向はデータセットして表示されるが、ユーザーが更新してもViewModelは変わらない。
双方向だと、データセットしたり、ユーザーがインプットしてもView、ViewModel共に更新される。
基本的には、単方向データバインディングで問題ないことが多いと思いますが、ユーザーからのインプット等がある際は双方向データバインディングの方が使いやすそうです。
実装
ここからが本題です。
ざっくりですが、実装の差異にフォーカスして記述していきます。
導入
build.gradle(:app)
android {
dataBinding {
enabled true
}
}
android内にdataBindindを有効にします。
ViewModel作成
class EditTextViewModel : ViewModel() {
val input = MutableLiveData<String>()
}
LiveDataで実装していきます。
LiveDataのメリット↓
レイアウトファイル(.xml)
<layout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewModel"
type="com.example.sampleapp.EditTextViewModel" />
</data>
~~~
</layout>
<layout>タグでレイアウトを括ります。
レイアウトファイルに上記で作成したViewModelを<data>タグ内に変数として定義します。
View
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val viewModel = EditTextViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
binding.viewModel = viewModel
binding.lifecycleOwner = this // LifecycleOwnerを設定
setContentView(binding.root)
}
}
作成したViewModelとレイアウトファイルのviewModelと紐付けます。
バインディングしたLifecycleOwnerをActivityを設定しておきます。
ここまでが共通部分になります。
単方向データバインディング
レイアウトファイル(.xml)
<EditText
android:text="@{viewModel.input}"
~~~
/>
双方向データバインディング
レイアウトファイル(.xml)
<EditText
android:text="@={viewModel.input}"
~~~
/>
以上です。簡単ですね。
@{viewModel.input} と @={viewModel.input} との違いですね。
結構ここの違いに気付かずに詰まった経験があります。。。
単方向データバインディングではLiveDataの使用とLifeCycleOwnerを設定は必要ないかなとも思いますが、基本的に必要な場面の方が多いと思います。
必要ない条件は下記です。
Viewの初期化後にデータの値を動的に変更しない場合
データの値が動的に変わってもViewの再描画の処理を自分で行う場合
最後に
差異自体はあまりないのですが、詰まった経験があったのとどっちがどっちか分からなくなるので忘備録として、メモ程度に単方向データバインディングと双方向データバインディングの違いを書いてみました。
データバインディングの導入方法も書いているので新たなアプリ作る際に自分自身も参考になればなっと思います。
データバインディング、好きぃ〜〜〜