findViewById... findViewById... find..View...by......  😵‍💫😵‍💫

 

findViewById에 지치셨나요??

🧐 언제까지 ViewId를 찾아다니실 건가요?

 

이제는 findViewById 없이 View Id 값을 바로 호출 할 수 있습니다.

DataBinding와 함께라면요! 

 

 

 

 

데이터 결합 라이브러리  |  Android 개발자  |  Android Developers

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 데이터 결합 라이브러리 Android Jetpack의 구성요소. 데이터 결합 라이브러리는 프로그래매틱 방식이 아니라 선

developer.android.com

 

 

DataBinding 활용하기(1)

✔️ Data Binding이란?
✔️ Data Binding 세팅
✔️ Binding 활용
✔️ @Binding Adapter 사용법

✔️ @Binding Adapter 매개변수 여러개 사용하기

 

 

DataBinding 활용하기(2)

✔️ Recyclervie에서 Data Binding 사용
✔️ BR

✔️ Data Binding 단점

 

 


 

📝 Data Binding이란?

 

Android JetPack 라이브러리 기능 중 하나로

xml의 데이터를 바인딩하여 불필요한 코드를 줄이는 방법입니다.

MVVM패턴을 구현할 때 LiveData와 같이 자주 사용됩니다.

 

" UI 요소와 데이터를 복잡한 로직으로 연결하지 않고

  선언적인 방식으로 결합 가능하게 도와주는 도구 "

 

(이렇게 글로 나열될 정의만 보면 이해하기 쉽지 않죠! 저도 그렇습니다!)

그렇다면 예제 소스를 통해 알아보시죠! 💁‍♂️💁‍♂️

 

 


 

🛠 Data Binding 세팅

 

Data Binding을 사용하기 위해서는 몇 가지 세팅이 필요합니다.

 

우선 build.gradle 파일에 dataBinding 속성을 추가합니다. 

 

build.gradle(Moudle: )

android {
        ...
        dataBinding {
            enabled = true
        }
    }

 

그 후 dataBinding을 사용하는 xml의 최상위 계층은 <layout>으로 구성되어야 합니다. 

activity_main.xml

<!-- 최상위 계층을 layout으로 적용 -->
<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">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/black"
        tools:context=".MainActivity">
        
        ...

</layout>

 

여기까지 작업 진행이 완료되었다면

"ActivityMainBinding" 이름으로 dataBinding Class가 자동으로 생성됩니다.

ActivityMainBinding

 

 

private lateinit var binding: ActivityMainBinding

 

위와 같이 ActivityMainBinding 자료형으로 변수 선언 시 

이미 자동으로 생성된 ActivityMainBinding Class가 존재하기 때문에

에러 없이 빌드 가능합니다.

 

( activity_main.xml에서 dataBinding을 적용했기 때문에

  ActivityMainBinding Class가 자동으로 생성되었습니다.

  만약 activity_intro.xml에서 dataBinding을 적용한다면

  ActivityIntroBinding Class가 생성될 것입니다. )

 

 

MainActivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        
        ...
     }
     
     ...
}

 

Activity에서 기존의 setContentView() 함수를 제거하고

DataBindingUtil.setContentView()로 교체합니다.

 

binding에서 View바로 접근

 

🎉  축하드립니다.   

 

여기까지 완료하셨다면

드디어 dataBinding을 사용할 준비가 끝났습니다.

 

위에 선언해둔 binding을 사용하여 xml View에 직접적으로 접근이 가능합니다.

binding. 이후 xml에 선언해둔 View id 값을 작성하면 

친절하게 자동완성으로 찾고자 하는 뷰 이름을 노출시켜 줍니다. 

 

 


 

🧑‍💻  Binding 활용

 

자 이제 DataBinding을 활용하여 재밌는 기능을 확인해보겠습니다.

 

xml에서도 변수 선언이 가능하다는 사실 알고 계셨나요? 🧐🧐

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="activity"
            type="kiu.dev.my_calculator.MainActivity" />
        
        <variable
            name="message"
            type="String" />
            
        <variable
            name="isTrue"
            type="Boolean" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        ...
        
        <TextView
            ...
            android:text="@{message}"/>
            
        
        <androidx.appcompat.widget.AppCompatButton
		...
		android:onClick="@{activity::onClickEvents}"/>
            
</layout>
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.activity = this
        binding.isTrue = versionData.isTrue()
        binding.message = versionData.getVersion()

 

 

위와 같이 <layout> 태그 아래 <variable>을 이용하여 선언이 가능합니다. 

이때 variable의 type 형태는 class, String, Integer, Boolean 등 

기존 변수 선언 때 자료형을 정해주는 것과 같습니다.

 

 

기본 사용법은 다음과 같습니다.  🧑‍💻🧑‍💻

android:text="@{변수명}"

 

변수가 Class 변수라면

android:text="@{Class변수명.함수명}"

ex)

Class FindText() {
	fun getText(): String {
    	return "FindText Str"
    }
}

<variable
    name="find"
    type="...FindText"/>

android:text="@{find.getText()}"

 

삼항 연산자도 활용 가능합니다. 

android:visibility="@{isTrue ? View.VISIBLE : View.GONE}"

 

클릭 이벤트에 대한 처리도 바로 가능합니다. 

android:onClick="@{activity::onClickEvents}"
MainActivity.kt
   
   fun onClickEvents(v: View) {
        when(v.id) {
            R.id.btn_click -> {
                Log.d("TestLog", "MainActivity btn_click onClickEvents")
            }
        }
    }

 

onClickEvents의 파라미터로 View 해당 뷰의 값이 들어오고

v.id 값으로 어떤 뷰의 클릭 이벤트 인지 구분하여 처리 가능합니다. 

 

Kotlin에서 ::(더블 콜론)은 Reflection이라고 하며

더 자세한 내용은 따로 정리하여 올리도록 하겠습니다.

(요즘 글 하나 작성하기가 너무 힘드네요 ... 🥲)

 

 


 

✔️ Binding Adapter 사용법

 

Binding Adapter는 xml View의 특정 속성 값이 적용되었을 때 

미리 정의해둔 로직을 실행시켜줍니다.

 

예시 소스를 한번 보시죠!  👀

(역시 말로만 사람을 이해시키는 건 어려운 일이죠...)

BindingAdapter.kt

object BindingAdapter {

    @BindingAdapter("app:bindText")
    @JvmStatic
    fun setTextView(view: TextView, str: String) {
        view.text = "version : $str"
    }
}

 

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private val versionData by lazy {
        AppVersion("1.0.0")
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.version = versionData.copy()

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="version"
            type="kiu.dev.my_calculator.data.AppVersion" />

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout>

        <TextView
            ...
            app:bindText="@{version.version}"/>
            
            ...
            
    </androidx.constraintlayout.widget.ConstraintLayout>

 

Binding Adapter와 Glide 라이브러리를 이용하면

ImageView를 더 간단하게 사용 가능합니다. 

 

@BindingAdapter("app:imgUrl")
@JvmStatic
fun loadImageUrl(view: ImageView, url: String?) {
    url?.let {
     Glide.with(view.context)
        .load(url)
        .fitCenter()
        .into(view)
    }
}

 

여기서 잠깐!  🤔🤔

Binding Adapter는 꼭 xml 속성 값을 하나만 받을 수 있을까? 

 

 

작업을 하다 보면 생각보다 여러 가지 Data들을 조합하거나

여러가지 조건들이 필요합니다.

 

@BindingAdapter("app:setVersion", "app:setStr", requireAll = false)
@JvmStatic
fun setTextView(view: TextView, version: String? = "", str: String? = "") {
    view.text = "version : $version , $str"
}

 

위와 같이 두 가지 이상의 xml 속성 값으로 파라미터를 받을 수 있고

requireAll 속성 값을 추가하여 모든 속성 값들이 반드시 모두 필요한지 정의합니다.

 

 

 


여기까지 저의 긴 글을 읽어주셔서 감사합니다.

제가 습관적으로 코딩을 하는 그날까지 습관적으로 코딩을 하기 위해 글 작성을 꾸준하게 해보겠습니다.

 

 

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기