Study Record

[안드로이드] 데이터 바인딩(Data binding)과 뷰 바인딩(View binding) 본문

안드로이드

[안드로이드] 데이터 바인딩(Data binding)과 뷰 바인딩(View binding)

초코초코초코 2023. 6. 19. 16:47
728x90

😶 findViewById() vs Data binding

View에 대한 접근을 얻기 위해 사용하는 함수인 findViewById()를 사용할 수 있다. 

val textView = findViewById<TextView>(R.id.name_tv)

findViewById() 함수가 작동되는 방식은 런타임 때 뷰 계층구조를 훑으면서 인자로 받은 id 값으로 알맞은 View를 찾아서 리턴해준다. 하나의 View를 연결할 때마다 findViewById() 함수를 사용하기 때문에 접근하려는 View 가 많아질수록 비용이 많이 든다.

 

 

또한, View 가 많지 않은 간단한 앱에서는 문제가 없지만 View 의 개수가 많아지고 계층 구조가 더 깊어지면 알맞은 View를 찾는데 시간이 오래 걸려 사용자의 앱 속도가 현저히 느려질 수 있다.

 

 

이런 findViewById() 의 문제점을 해결하는 하나의 해결책으로 View에 대한 접근을 포함한 객체를 만드는 것이다. 이 객체를 Binding이라고 부르며 앱 전체에서 사용할 수 있다. 이 binding 객에게 한번 앱에서 만들어지면 View와 다른 data를 View 계층구조를 훑지 않고 바로 binding 객체로 접근할 수 있다. 이 기술을 Data Binding이라고 부른다!

 

 

🙄 Data Binding 이점

  • findViewById() 를 사용할 때보다 코드가 더 간결하고 읽기 쉽고, 유지 관리하기 쉬워진다.
  • data와 View를 분리할 수 있다.
  • 런타임 때 앱과 상호작용하는 과정에서 안드로이드 시스템이 View 계층구조를 탐색할 필요가 없어진다.
  • View에 접근할 때 데이터 타입을 실수할 일이 없어진다. (type safety) - ex. TextView, EditText 등

 

 

 

😶 Data Binding 사용하기

 

build.gradle(Moudle: [App Name]) 파일에 데이터 바인딩을 사용한다고 선언한다.

android {
	...
    buildFeatures {
    	dataBinding true
    }
}

sync now 버튼을 누른 뒤, 필요하다면 File > Sync Project with Gradles files를 누른다.

 

 

이제 xml 파일에 제일 상위에 <layout> 태그로 감싸준다. 데이터가 있다면 <data> 태그와 <variable> 태그를 이용해 현재 레이아웃에서 사용할 데이터들의 클래스 타입을 선언해 준다.

 

다음 예시는 name과 nickname 텍스트 뷰와 name 버튼으로 이루어져 있는 화면인데, name 버튼을 누르면 name 과 nickname을 표시해 주는 간단한 기능을 가지고 있다.

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <data>
        <variable
            name="myInfo"
            type="com.example.basic_text.MyName" />
    </data>

    <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"
        android:padding="20dp"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/name_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@={myInfo.name}"
            android:textColor="@color/black"
            android:textSize="18sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/nickname_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="@={myInfo.nickName}"
            android:textColor="@color/black"
            android:textSize="18sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/name_tv" />

        <Button
            android:id="@+id/name_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="Name"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/nickname_tv" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

- MyName 데이터 클래스

package com.example.basic_text

data class MyName(
    var name: String = "",
    var nickName: String = ""
)

 

예시에서 알 수 있듯 현재 레이아웃에서 사용할 데이터 이름(myInfo)을 적용할 TextView의 text에 @={myInfo.name}과 같은 형식으로 적용해 준다.

 

 

Activity에서 binding 객체를 선언하고 setContentView(R.layout.activity_main) 함수를 binding = DataBindingUitl.setContentView(this, R.layout.activity_main) 함수로 선언해 준다.

 

생성된 binding 객체의 이름은 레이아웃 파일 이름을 기반으로 하여 파스칼 표기법으로 변환하고 Binding 접미사를 추가한다. 따라서 activity_main.xml 에서 생성되는 클래스는 ActivityMainBinding이다.

class MainActivity : AppCompatActivity() {
    private lateinit var binding : ActivityMainBinding
    private val myName: MyName = MyName("Aleks Heaecky", "Android")
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        binding.nameBtn.setOnClickListener {
            setName()
        }
    }

    private fun setName() {
        binding.myInfo = myName
        // binding.invalidateAll()
    }
}

binding 객체로 View와 미리 설정한 data에 접근할 수 있는데 View 는 id 값으로 접근한다. id 가 name_btn 이라면 "_" 는 다음 오는 글자를 대문자로 인식해주므로 binding.nameBtn 으로 접근할 수 있다.

 

binding 객체에 미리 설정한 data 에 접근할 수 있는데 이름을 myInfo로 했다면 binding.myInfo로 가져올 수 있다.  

<data>
    <variable
        name="myInfo"
        type="com.example.basic_text.MyName" />
</data>

myInfo는 name과 nickname 텍스트뷰와 서로 연결되어 있으므로 binding.myInfo 의 값만 변경해주면 자동으로 name 과 nickname 텍스트 뷰의 텍스트 값이 변경된다!

 

 

- binding.invalidateAll() 함수는 binding 객체가 업데이트된 값으로 UI를 refresh 할 수 있다.

 

 

 

😶 뷰 바인딩(View Binding)

View Binding 도 data Binding과 비슷하게 findViewById()를 대체하는 개념으로 View 데이터를 Binding 객체로 접근할 수 있다. 하지만 data에 대해서는 지원하지 않는다.

 

 

😶 뷰 바인딩 사용방법

 

먼저 gradle 파일 viewBinding을 true로 한다.

android {
    ...
    buildFeatures {
        viewBinding = true
    }
}

 

생성된 Binding 객체의 이름은 Data Binding과 마찬가지로 레이아웃 파일 이름을 기반으로 하여 파스칼 표기법으로 변환하고 Binding 접미사를 추가한다. 만약 xml 파일의 이름이 activity_main.xml이라면 Binding 객체 이름은 ActivityMainBinding이다. 

class MainActivity : AppCompatActivity() {

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

        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        binding.textView.text = "textView Example"
    }
}

setcontentView 함수로 선언한 binding 객체로 View를 생성하고 접근할 수 있다.

 

 

 

 

생성된 결합 클래스  |  Android 개발자  |  Android Developers

생성된 결합 클래스 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 데이터 결합 라이브러리는 레이아웃의 변수 및 뷰에 액세스하는 데 사용되는 결합 클래

developer.android.com

 

728x90