물에 살고싶은 개발자

[Databinding] 2. 데이터바인딩 BindingAdapter 사용법 본문

Android

[Databinding] 2. 데이터바인딩 BindingAdapter 사용법

돼지사랑 2022. 7. 2. 17:02

 

저번 글에 이어 바인딩어댑터의 사용법을 적어볼까 한다. 

저번 글에서 사용법을 설명한 데이터 바인딩에 대한 지식이 있어야 이해하기 쉬울것이다.

 

일단 최대한 요약해서 결론부터 적어보자면, 

BindingAdapter 는 각 뷰의 커스텀 Method가 가능하게 해주는것. 이라고 이해하면 된다.

BindingAdapter에 원하는대로 사용법에 맞춰 Method를 작성하고 그것을 레이아웃을 작성할때 가져다 쓰면 되는것 ! 

 

당연히 이것만으로는 설명이 부족할테니 이제 자세한 사용법에 대해 알아보자.

저번 글에서 했던 세팅이면 그대로 사용 가능하니 세팅은 패스하겠다.

그리고 예시로 드는 프로젝트 역시 저번에 이어서 사용할 예정이다.

 

1. BindingAdapter object 생성 (CustomBindingAdapter.kt) 

import android.widget.TextView
import androidx.databinding.BindingAdapter

object CustomBindingAdapter {

    @BindingAdapter("nameSetText")
    @JvmStatic
    fun setNameText(view: TextView, text: String?){
        view.text = "이름 is $text"
    }

    @BindingAdapter("ageSetText")
    @JvmStatic
    fun setAgeText(view: TextView, age: Int?){
        view.text = "나이 is $age"
    }
}

왜 class가 아닌 object를 사용해야하나, 왜 @JvmStatic 애노테이션을 사용하나 등의 의문들은 설명하지 않을 예정이다.

이 글의 목적은 사용설명에 있기때문 ! 그러므로 일단은 무지성으로 위 코드스니펫의 문법에 따라 작성해주자.

(대신 만들때 문제가 될법한것들이나 팁은 생각나거나 내가 삽질을 할때마다 여기에 업데이트할 예정이다.)

 

다만, 알아야 할것들은 설명하고 넘어가겠다.

1. 네이밍.

@BindingAdapter("nameSetText")

위 코드에 대한 부분은 xml에서 사용할때 속성명으로 사용할 부분이다. nameSetText가 그대로 속성명이 되는것. 그러므로 왠만하면 기존에 있던 속성명과 겹치지않고, 다른 커스텀 Method들과도 겹치지 않는것이 좋다. 아래에서 설명할 xml에서의 사용법에서 사용할 이름이기 때문!

 

2. 파라미터

fun setNameText(view: TextView, text: String?)

BindingAdapter는 기본적으로 파라미터를 두개를 갖는다. 첫번째는 이 Method를 속성으로 사용하는 view 이므로, 해당 view와 타입을 맞춰줘야한다. 그리고 두번째는 들어오는 값인데, 아래 코드처럼 

app:nameSetText="@{user.name}"

이렇게 했을 시 user.name이 text로 들어오게 되는것. 역시 이것도 타입을 맞춰 줄 필요가 있다. 

 

2. xml파일에서의 사용법

어려울것 없으니 일단 예제부터 보자

<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/nameTv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:nameSetText="@{user.name}"
            tools:text="이름이 들어가는 텍스트뷰"
            android:layout_marginStart="20dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/ageTv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:ageSetText="@{user.age}"
            tools:text="나이가 들어가는 텍스트뷰"
            android:layout_marginStart="20dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@+id/nameTv"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

가운데 잘 보면 app:nameSetText="@{user.name}" 와 app:ageSetText="@{user.age}"가 있다.

꼭 데이터바인딩을 연계하지 않더라도 이런식으로 활용할 수 있음을 알 수 있다. 

 

 

이렇게 사용하면 끝! 아주 심플하다. 이것으로 BindingAdapter의 사용법에 대한걸 마치겠다.

 

아래는 추가 팁

 

추가 팁 1. Glide 등의 라이브러리를 사용하거나 하는 경우 context가 필요할 수 있는데, 이는 각 뷰에서 가져오면 된다.

예제는 아래와 같다. 

    @BindingAdapter("nameSetText")
    @JvmStatic
    fun setText(view: TextView, text: String?){
        val context = view.context
    }

추가 팁 2. 파라미터를 여러개 늘리고 싶을땐 아래와 같이 하면 된다.

    @BindingAdapter(value = ["text1", "text2" ] , requireAll = false)
    @JvmStatic
    fun setNameText(view: TextView, text1: String? , text2: String? ){
        view.text = "1. $text1 2. $text2 "
    }

사용법만 살짝 달라질뿐 달라질것은 없다 이 경우 xml파일에선 이렇게 사용하면 된다.

        <TextView
            android:id="@+id/nameTv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:text1="@{user.name}"
            app:text2="@{String.valueOf(user.age)}"
            tools:text="이름이 들어가는 텍스트뷰"
            android:layout_marginStart="20dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

다양한 사용법이 가능하다는것을 알리기 위해 1,2번을 각각 다르게 넣어봤다. 이 외에도 사용가능한것들이 있으니, 각자 필요한것들을 찾아보면서 사용하면 좋을것이다.

 

추가 팁 3. 아마 이미 떠올린사람이 있을수도있는데, 평범하게 액티비티나 프래그먼트에서도 아래와 같이 하면 사용 가능하다. 단 이때는 @BindingAdapter 애노테이션에 value로 들어가는 이름이 아닌 함수의 Method명을 사용해야한다.

setNameText(binding.nameTv,"홍킬동",20.toString())

 

추가팁 끝!

Comments