DataBinding에 대해 알아보자 | Android Study

hoya·2022년 3월 9일
0

Android Study

목록 보기
11/19
post-thumbnail

기존에 작성했던 ViewBinding 포스트를 참고하면 이해가 더 빠를 것이다.

🤔 DataBinding?

Data - View의 연결 작업을 레이아웃에서 처리할 수 있게 도와주는 라이브러리

DataBinding 은 ViewBinding이 하는 역할에 추가적으로 동적 UI 컨텐츠를 선언하고, 양방향 데이터 결합도 지원한다.

🤗 장점

  • 코드 가독성이 향상되고, 코드량을 줄일 수 있다.
  • XML 리소스를 보고 View에 어떤 데이터가 들어갈지 예측할 수 있다.
  • 리사이클러뷰 사용 시 각각의 아이템을 일일이 정해주지 않고 XML에서 처리할 수 있다.
  • 실시간으로 데이터 변경이 가능하다.
  • MVVM 패턴 구현에 용이하다.

😡 단점

  • 클래스 파일이 증가해 앱 사이즈를 증대시킬 수 있다.
  • 디버깅 과정에서 어려움을 겪을 수 있다.
  • 일부는 액티비티, 일부는 XML에서 데이터 작업을 수행한다면 오히려 혼선을 겪을 수 있다.
  • ViewBinding에 비해 퍼포먼스 효율이 떨어지고 용량이 증가한다. 단순히 findViewById() 를 대체할 용도라면 ViewBinding을 사용하는 것이 옳다.

직접 구현해보면서 어떤 부분이 좋은지 알아보도록 하자.


🙃 실습

📌 기본 설정

    android {
        buildFeatures {
                 dataBinding = true
        }
    }

ViewBinding 과 설정 방법이 거의 동일하다. 그러나, ViewBinding 과는 다르게 빌드하자마자 Binding 클래스가 생성되는 것은 아니다. 따로 XML에서 설정을 해주어야만 Binding 클래스가 생성된다.

데이터 클래스 설정

data class User(
    var nickname: String?,
    var name: String?
)

📌 XML 설정

위의 레이아웃과 동일하게 생성할 것이다.


<?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"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
      <!-- Databinding -->
        <variable
            name="user"
            type="com.dongyang.android.mvvm_sample.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".EditUserProfileActivity">

        <TextView
            android:id="@+id/tv_nickname"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="30dp"
            android:hint="edit your nickname"
            android:text="@{user.nickname}"
            android:textColor="@color/black"
            android:textSize="20sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="5dp"
            android:hint="edit your name"
            android:text="@{user.name}"
            android:textColor="@color/black"
            android:textSize="20sp"
            android:textStyle="bold" />


        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginTop="30dp"
            android:background="@color/black" />

        <EditText
            android:id="@+id/edt_nickname"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="20dp"
            android:hint="edit your nickname" />

        <EditText
            android:id="@+id/edt_name"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:hint="edit your name" />

        <Button
            android:id="@+id/btn_edit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="EDIT" />

    </LinearLayout>
</layout>

기존에 알던 레이아웃 구조에서 조금 변화가 생긴 것을 알 수 있다.

  1. 가장 바깥쪽에 <layout> 태그가 추가되었다.
  2. 그 안에 <data> 태그가 추가되었다.
  3. 기존에 사용하던 레이아웃이 가장 하단으로 이동되었다.

<layout> 태그의 경우 크게 어려운 점은 없고, 그저 추가만 해주면 된다. 그렇다면 주목해야 할 태그는 <data> 태그인데, 해당 태그 안에 <variable> 이라는 태그가 추가되었다. 어떤 역할을 맡는걸까?

위에서 이야기했던 Data - View 연결을 여기서 진행한다. type 에는 연결하고 싶은 데이터 클래스의 경로를 지정하고, name 에는 XML에서 사용할 이름을 설정해주면 된다. 위 소스를 통해, User 데이터 클래스에 접근이 가능해졌다.

사용 방법은 <TextView> 태그를 보면 알 수 있다. 변수를 @{} 구문안에 넣어 해당 데이터를 뷰와 바인딩할 수 있다. 위의 XML에서는 User의 이름과 닉네임을 바인딩한 것을 확인할 수 있다.

추가적으로, 이 과정을 거치면 바인딩 클래스가 생성되며, 이름은 ViewBinding과 마찬가지로 카멜 표기론에 의거하여 지어진다.
list_fragment.xml -> ListFragmentBinding
hoya_activity.xml -> HoyaActivityBinding


📌 Activity 에서 사용하기

class EditProfileActivity : AppCompatActivity() {

    private val binding: ActivityEditProfileBinding by lazy {
        ActivityEditProfileBinding.inflate(layoutInflater)
    }

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

        binding.btnEdit.setOnClickListener {
            setUserData()
        }
    }

    fun setUserData() {
        val setNickName = binding.edtNickname.text.toString()
        val setName = binding.edtName.text.toString()

		/* ViewBinding 
        binding.tvName.text = setName
        binding.tvNickname.text = setNickName
        */
        
        val userData = User(setNickName, setName)
        binding.user = userData // XML에 데이터 전달
    }
}

XML의 text 를 액티비티에서 설정하는 것이 아니라, 오로지 전달만 해주는 모습을 확인할 수 있다. 지금은 그저 두 개의 TextView라서 와닿지 않을 수 있지만 만약 10개 이상의 TextView가 존재했고, 거기에 일일이 데이터를 넣어주어야 했다면 액티비티의 코드가 굉장히 난잡해졌을 것이다.

👀 현재는 EditText의 값을 받아와서 액티비티에서 받고 다시 XML로 전달하는 과정을 거치고 있지만, 더 자세히 파고들면 2-way binding 이라고 해서 EditText의 값이 변경되면 바로 TextView에 넣는 방법도 가능하다. 해당 포스팅은 기초적인 정보를 담고 있으므로 이 방법은 추후에 따로 작성하도록 한다.


📌 표현식 사용하기

구글 공식 문서에 기재되어 있는 표현식은 아래와 같다.

  • 산술 + - / * %
  • 문자열 연결 +
  • 논리 && ||
  • 바이너리 & | ^
  • 단항 + - ! ~
  • 전환 >> >>> <<
  • 비교 == > < >= <=(<는 <으로 이스케이프 처리해야 함)
  • instanceof
  • 그룹화 ()
  • 리터럴 - 문자, 문자열, 숫자, null
  • 변환
  • 메서드 호출
  • 필드 액세스
  • 배열 액세스 []
  • 삼항 연산자 ?:

이 중에서 예시로 삼항 연산자를 사용해보도록 하자. 기존 유저 데이터 클래스에 gender 변수를 추가하고, 값이 0이면 "남성"을 출력하고, 1이면 "여성"을 출력하는 예시를 만들어보자. 우선, 데이터 클래스를 먼저 추가한다.

데이터 클래스

data class User(
    var nickname: String?,
    var name: String?,
    var gender: Int?
) {
    companion object {
        const val GENDER_MALE: Int = 0 // 상수
        const val GENDER_FEMALE: Int = 1 // 상수
    }
}

Layout


	...
    
    <data>
        <import type="com.dongyang.android.mvvm_sample.User"/>
        <!-- 레이아웃 파일 내에서 클래스 참조 -->
        <variable
            name="user"
            type="com.dongyang.android.mvvm_sample.User" />
    </data>

	...
    
    <TextView
        android:id="@+id/tv_gender"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="5dp"
        android:hint="edit your gender"
        android:text="@{(user.gender == User.GENDER_MALE) ? &quot;남성&quot; : &quot;여성&quot;}"
       
        android:textColor="@color/black"
        android:textSize="20sp"
        android:textStyle="bold" />
    

android:text 부분을 보면 삼항 연산자를 사용한 것을 볼수 있다. 텍스트에 String 형태로 넣기 위해서 원래는 큰 따옴표를 넣어야 하지만, 이미 큰 따옴표를 적은 상태이기 때문에 &quot 을 이용하여 큰따옴표를 따로 붙여주도록 한다.

이렇게 하면 아래와 같은 실행 결과를 얻을 수 있을 것이다.


📌 리사이클러뷰에서 사용하기

리사이클러뷰에서 사용할 때도 크게 다른 점은 없다. 어댑터에서 아래와 같이 설정하면, 데이터바인딩이 적용되는 것이다.

class UserRecyclerViewAdapter(
) : RecyclerView.Adapter<UserRecyclerViewAdapter.ViewHolder>() {

    private var items = listOf<UserProfile>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = UserlistBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = items[position]
        /* ViewBinding
        holder.userId.text = item.id.toString()
        holder.userName.text = item.name
        holder.userPhone.text = item.phone
        holder.userAddress.text = item.address
         */

        holder.setData(item)
    }

    override fun getItemCount(): Int = items.size

    inner class ViewHolder(private val itemBinding: UserlistBinding) : RecyclerView.ViewHolder(itemBinding.root) {

        fun setData(userProfile : UserProfile) {
            itemBinding.item = userProfile
        }

        /* ViewBinding
        val userId = itemBinding.itemId
        val userName = itemBinding.itemName
        val userPhone = itemBinding.itemPhone
        val userAddress = itemBinding.itemAddress
         */
    }
}

한 눈에 보아도 주석을 제외하고 보면 코드가 줄어든 것을 확인할 수 있다.


참고 및 출처

모던 안드로이드 아키텍처
오늘의 코드

profile
즐겁게 하자 🤭

0개의 댓글