DataBinding은 Android JetPack의 일부 라이브러리이며 상용구 코드를 쉽게 제거하는 코드를 작성하는데 도움이 되는 라이브러리 모음입니다.
DataBinding 라이브러리는 간단하게 정의 한다면 UI 요소와 데이터를 프로그램적 방식으로 연결하지 않고 선언적 형식으로 결합할 수 있게 도와주는 Jetpack 라이브러리이다.
이는 글로 설명하는 것 보다는 코드를 본다면 바로 이해할 것이다.
프로그램적 데이터 연결 방식
val textview = findViewById<TextView>(R.id.sample)
textview.text = "프로그램적 데이터 연결"
binding.sample.text = "프로그램적 데이터 연결 "
위에 코드에서 보는 것처럼 소스 코드에서 데이터를 집어넣는 것이 프로그램적 데이터 연결 방식이고
선언적 데이터 연결 방식
//activity_main.xml
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@={user.example}" />
다음과 같이 XML에 코드에 직접 넣어서 데이터를 집어넣는 것이 선언적 데이터 연결 방식이다
즉 DataBinding은 데이터와 View를 연결하는 작업을 layout에서 처리하는 기술인 것이다.
구글 공식문서에서는 DataBinding 기술을 MVVM패턴에서의 사용을 권장합니다.
- XML에 데이터를 binding하여 boiler plate를 줄일 수 있다.
- MVVM 패턴에서 DataBinding을 사용한다면 observer 패턴을 이용하여 데이터가 변경된다면 바뀐 데이터가 View에서도 반영되어 변경된다.
- Databinding을 사용한다면 findViewById()를 쓰지 않아도 XML에 만든 View들을 자동으로 만들어준다.
3번에 대한 예시 코드를 작성해보겠습니다.
findViewById
setContentView(R.layout.hello_word) val textview = findById<TextView>(R.id.textView) textview.text = "Hello World"
DataBinding
binding = DataBindingUtil.setContentView(this,R.layout.hello_word) binding.textview.text = "Hello World"
Acess를 위한 코드는 DataBinding이 findViewById보다 직관성이 높고 compile시간이 더 짧게 걸립니다. 또한 binding process는 모든 View에서 단일 패스를 만들어 필드에 View를 할당합니다. 하지만 findViewById를 실행하면 View 계층 구조를 찾을 때 마다 이동을한다.
java
android{
dataBinding{
enable true
}
}
Kotlin
dataBinding{ android.buildFeatures.dataBinding = true }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/text_email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
위의 일반적인 레이아웃 파일에서 및 태그로 래핑해 보겠습니다.
코딩으로 해도 상관없지만 Show Context Actions을 이용할 수 있습니다.
<?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">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text_email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
에서 데이터에 액세스하도록 변수를 설정할 수 있습니다. 데이터 태그는 주로 두 가지 사용 요소를 가지고 있습니다. 하나는 name이고 다른 하나는 type입니다.
다음은 MainViewModel이 있다고 가정하고
```
package com.sample.databinding
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class MainViewModel :ViewModel() {
private val _userEmailLD by lazy { MutableLiveData("test@gmail.com") }
val userEmailLD: MutableLiveData<String> by lazy { _userEmailLD }
}
레이아웃 파일에서 변수를 다음과 같이 정의합니다.
```
<data>
<variable
name="viewModel"
type="com.sample.databinding.MainViewModel" />
</data>
변술를 정의했으므로 이제 레이아웃 자체에서 ViewModel 데이터를 사용할 수 있습니다. 변수에서 값을 할당하려면 다음 구문을 사용해야하는데 바로 @{}입니다. ViewModel의 인스턴스에서 이메일을 가져와 TextView로 설정합니다.
```
<TextView
android:id="@+id/text_email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.userEmailLD}"
android:textColor="@color/black"
/ >
xml 부분이 끝나고 다음은 정의된 변수와 xml을 사용하기 위해 Activity.kt에서 코드를 선언하겠습니다.
setContentView(R.layout.activity_main)
다음과 같이 일반적인 setContentView가 아닌
val binding: ActivityMainBinding =
DataBindingUtil.setContentView(this, R.layout.activity_main)
이렇게 작성해준다는 차이가 있습니다.
DataBindingUtil은 레이아웃에서 ViewDataBinding으 생성하는 유틸리티 클래스입니다.
각 레이아웃 파일에 대한 바인딩 클래스가 생성되고 생성된 클래스 사용되는 기본 명명 규칙은 레이아웃 파일의 이름을 기반으로 합니다. activity_main.xml의 경우 -> ActivityMainBinding으로 쓰입니다.
MainActivity.kt
class MainActivity : AppCompatActivity() {
val mainViewModel: MainViewModel by ViewModelLazy(
MainViewModel::class,
{ viewModelStore },
{ defaultViewModelProviderFactory }
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding =
DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.apply {
lifecycleOwner = this@MainActivity
viewModel = mainViewModel
}
}
}
! LiveData를 데이터 태그의 변수로 사용하려면 수명 주기 인식 관찰 가능항목이므로 연결한 수명 주기 소유자를 지정해야합니다. binding은 그러한 역할을 수행합니다.
binding.textEmail.text = mainViewModel.userEmailLD.value
다음과 같이 값을 넣어줍니다.
또한 LiveData를 사용하기 때문에 Observer Pattern을 활용해서 값이 변경되는지도 확인을 하면
mainViewModel.userEmailLD.observe(this@MainActivity, {
binding.textEmail.text = it
})
값이 변경이 된다면 View에서도 값이 바뀌는 것을 확인할 수 있습니다.
활동을 레이아웃에 바인딩 했지만 XML의 변수에 값을 할당하지않았기에 값을 설정할 수 있도록 선언해줍니다.
binding.viewModel = mainViewModel
다음 글에서는 Click 이벤트와 DataBinding이 단순히 데이터 값을 바꾸는 것만이 아닌
View 또한 참조하여 속성을 변경할 수 있다는 내용을 작성해보려고합니다. 읽어주셔서 감사합니다.