[Android] DataBinding

HEETAE HEO·2022년 4월 29일
0

DataBinding

목록 보기
1/3
post-thumbnail

DataBinding

DataBinding은 Android JetPack의 일부 라이브러리이며 상용구 코드를 쉽게 제거하는 코드를 작성하는데 도움이 되는 라이브러리 모음입니다.

DataBinding 라이브러리는 간단하게 정의 한다면 UI 요소와 데이터를 프로그램적 방식으로 연결하지 않고 선언적 형식으로 결합할 수 있게 도와주는 Jetpack 라이브러리이다.

프로그래점적 데이터 연결 방식 vs 선언적 데이터 연결 방식

이는 글로 설명하는 것 보다는 코드를 본다면 바로 이해할 것이다.

프로그램적 데이터 연결 방식

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패턴에서의 사용을 권장합니다.

DataBinding의 사용 이유

  1. XML에 데이터를 binding하여 boiler plate를 줄일 수 있다.
  2. MVVM 패턴에서 DataBinding을 사용한다면 observer 패턴을 이용하여 데이터가 변경된다면 바뀐 데이터가 View에서도 반영되어 변경된다.
  3. 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 계층 구조를 찾을 때 마다 이동을한다.

데이터 바인딩 라이브러리 사용

1 : Gradle 파일에서 데이터 바인딩을 활성화 합니다.

java

android{
	
    dataBinding{
    	enable true
        }
    }

Kotlin

dataBinding{
	android.buildFeatures.dataBinding = true
}

2 레이아웃 파일을 데이터 바인딩 레이아웃으로 변환

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>

3 : 데이터 태그를 사용하여 변수 설정 및 동적 데이터 연결

에서 데이터에 액세스하도록 변수를 설정할 수 있습니다. 데이터 태그는 주로 두 가지 사용 요소를 가지고 있습니다. 하나는 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" 
 / >

4 : Activity

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에서도 값이 바뀌는 것을 확인할 수 있습니다.

5 : 바인딩 인스턴스를 사용해 데이터 변수에 값 할당

활동을 레이아웃에 바인딩 했지만 XML의 변수에 값을 할당하지않았기에 값을 설정할 수 있도록 선언해줍니다.

 binding.viewModel = mainViewModel

마치며

다음 글에서는 Click 이벤트와 DataBinding이 단순히 데이터 값을 바꾸는 것만이 아닌
View 또한 참조하여 속성을 변경할 수 있다는 내용을 작성해보려고합니다. 읽어주셔서 감사합니다.

profile
Android 개발 잘하고 싶어요!!!

0개의 댓글