코딩 (독학)/★ Kotlin

[Android : Kotlin] ViewBinding VS DataBinding ?

짱득이 2022. 1. 26. 17:39
300x250
반응형

🧐 ViewBinding

  • View와 상호 작용하는 코드를 더욱 쉽게 작성할 수 있도록 도와주는 기능 (기존의 익스텐션과 동일)
  • xml 파일에서 각 View는 id 값을 가진다.

🧐 ViewBinding, 왜 도입 되었는가?

각각의 View 요소들을 객체화 시켜 사용하기 위해서는 일일이 fineViewById를 작성 해 줘야하는데, 이것이 매우 골칫거리였다. 때문에, View 요소들을 객체화 시키지 않고 바로 사용하여 불필요한 코드를 줄이기 위해 도입되었다.

(익스텐션과 도입 이유는 동일하나, 고질적인 문제를 없애고 더욱 안정적이다.)

 

👀 조금 더 자세하게 알아보자.

  • View BInding은 모듈 별로 사용을 설정해야 한다.
  • 설정이 되면 각 xml 파일에 대해 Binding Class를 자동 생성한다.
  • Binding Class Instance는 ID를 가지고 있는 모든 View에 대한 직접적 참조를 포함한다.
  • 그에 따라 findViewById를 사용하지 않고 대체 할 수 있다.

(Kotlin에서는 Binding Class 생성 없이 Layoud ID 값만 참조하여 View를 사용하는데,

이것은 View Binding과는 조금 다른 관점이고, 거의 DataBinding과 비슷하다..)

 

🧠 Setting ?

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

 

 

android {
    ...
    viewBinding {
        enabled=true
    }
}

두가지 방법 중 편한거로 사용하면 된다.


🧐 ViewBinding 특징

  • ViewBinding은 Build 과정에서 생성된다.
  • 끝에 Binding이라는 단어가 붙는다.
  • pascalCase + camelCase 표기법에 따라 Naming 규칙이 적용된다.
  • ID가 존재하지 않는 View에 대해서는 클래스에 참조가 존재하지 않는다.
  • getRoot() Method가 자동 포함된다. Layout File의 Root View에 관한 직접 참고 제공.

🧐 findViewById와의 차이

  • Null Safety - View 직접 참조로 없는 아이디로 Null Point Exception 발생 안함.
  • Type Safety - View Type이 일치함으로 Class Cast Exception 발생 안함.

👀 DataBinding과의 차이

ViewBinding, DataBinding 모두 뷰를 직접 참조하는데 사용할 수 있는 Binding Class를 제공한다.

확실히 ViewBinding은 보다 단순한 처리의 경우 적합하다.

  • 더욱 빠른 Compile => Annotation (주석)처리가 필요 없어서 컴파일이 빠르다.
  • 사용 편의성 => Tag처리된 xml 불 필요로 사용이 용이함. (모듈에서 binding 사용 설정만을 통해 자동으로 모든 레이아웃의 binding class 생성)

💉 DataBinding과의 차이에서 오는 ViewBinding의 단점 ?

  • Layout에서의 표현식 혹은 변수를 제공하지 않으므로, 동적인 UI 콘텐츠를 생성 할 수 없다. => (dataBinding은 xml 파일에 Data를 view와 연결시켜 두면 data가 변할 때 따로 세팅 해 주지 않아도 변경되게 함)
  • Two-Way-Data Binding을 제공하지 않음. (ex. bindingAdapter)

🔎 findViewById()의 문제점

일반적으로 안드로이드를 처음 배우면 findViewById()를 사용하여 각 View Component 요소들을 객체로 만들어 사용한다.

(위 과정을 통해 xml에 정의된 id를 가진 View들을 코드 단에서 사용할 수 있기에)

// kotlin
val textView = findViewById<TextView>(R.id.tv_first)

// java
TextView textView = (TextView) findViewById(R.id.tv_first)

 

🩸 findViewById()의 치명적인 단점

  • 컴포넌트가 10개만 되어도 같은 코드 10줄을 추가하게 됨. (많아지면 많아질 수록 더러워짐)
  • findViewById()는 사용하기에 꽤나 무거운 Function.
  • null 값에 상대적으로 안전하지 못함. (존재하지 않는 Component / id를 불러오는게 가능함. 물론 동작은 안되지만..)

🎉 정리하자면..

ViewBinding / DataBinding이 꼭 무엇 하나가 좋다기 보단, Project의 상황과 경우에 맞게 사용하는 것이 가장 좋다.

Method Elegance Compile Type Safety Build Speed
findViewById
ViewBinging
DataBinding
Butterknife
Kotlin Synthethic

💫 공통 사항 (viewBinding / dataBinding 세팅 방법)

1. Gradle (그레이들) 에서 관련 옵션 활성화

(단, Android Studio 4.1 이상, 최신 버전에서 설정하기를 권장.)

[ Gradle Scripts ] ▶ [ build.gradle(Module: 프로젝트명) ] 파일에 접근하여 아래와 같은 코드 작성

android {
    ...
    buildFeatures {
    // 뷰 바인딩 활성화를 원한다면
        viewBinding true 
    // 데이터 바인딩 활성화를 원한다면
        dataBinding true
    }
    ...
}
android {
    ...
    viewBinding {
        enabled = true
    }
    
    dataBinding {
        enabled = true
    }
    ...
}

 

추가적으로, Android Studio 4.0 부터는 buildFeatures에서 Param을 작성하는것으로 바뀌었다고 한다.

근데 왜 오류는 안나지? ㅋㅋ;;

 

이후 Android Studio 우측 상단의 Sync Now 를 클릭하여 Gradle 수정사항을 프로젝트에 반영

 

* dataBinding의 경우 아래 사진처럼 kotlin-kapt plugin을 설정하라고 나올 수 있음.

그렇다면 아래와 같이 최상단 plugin 단에 코드를 추가하면 됨.

plugins {
        ...
        id 'kotlin-kapt'
        ...
    }

...
...

 


🔎 본격적으로 사용 해 보기 (viewBinding기준)

package com.jjangdeuk.whentest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView

class MainActivity : AppCompatActivity() {

    var flag = 0
    val txt: TextView = findViewById(R.id.textView)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val btn: Button = findViewById(R.id.btnSwitch)

        btn.setOnClickListener {
            switch()
        }
    }

    private fun switch() {
        when (flag) {
            0 -> {
                txt.text = "와따 쩌노"
                flag = 1
            }
            1 -> {
                txt.text = "왐마 돌아갔농"
                flag = 0
            }
        }
    }
}

 

원래대로라면 위 코드와 같이 findViewById를 사용하여 일일이 View를 찾아다녀야 하고, 코드가 길어지지만 이제 extensions의 기능을 대체한 viewBinding을 사용해 아래와 같이 코드를 고칠 수 있다.

package com.jjangdeuk.whentest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import com.jjangdeuk.whentest.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity(){
    var flag = 0

    lateinit var binding : ActivityMainBinding


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

        binding = ActivityMainBinding.inflate(layoutInflater)

        val view = binding.root
        setContentView(view)

        binding.btnSwitch.setOnClickListener(){
            switch()
        }

    }

    private fun switch() {
        val transaction = supportFragmentManager.beginTransaction()
        when(flag) {
            0 -> {
                binding.textView.text = "와따 쩌노"
                flag=1
            }
            1 -> {
                binding.textView.text = "왐마 돌아갔농"
                flag=0
            }
        }
        transaction.commit()
    }
}

당장 두 코드가 길지 않기 때문에 크게 차이나는지 잘 모르겠지만, viewBinding 세팅으로 인해 View를 찾아다니지 않고도 binding.[View 요소].[Function] () 등으로 사용할 수 있기 때문에 코드의 귀차니즘이 현저히 줄어들었고, 앞으로도 사용성이 좋아보인다.

 

 

참고한 블로그에 따르면.. 이후에 xml에 클래스를 연결하고, 해당 클래스가 변경되면 연결된 여러개의 view가 한번에 변경되거나 BindingAdapter를 이용해 ImageView에 Glide로 이미지 표시하기 등과 같은 것 들을 할 수 있고, LiveData를 사용하면 data가 변경될 때 view도 같이 변경되는 좋은 경험을 할 수 있다는데.. 이건 나중에 한번 해 봐야겠다 ㅎㅎ

* 참고한 블로그
https://paddre.tistory.com/214
https://duckssi.tistory.com/42
https://dev-imaec.tistory.com/41
https://dev-imaec.tistory.com/40
https://dev-imaec.tistory.com/37

* 응용하기 좋은 블로그 포스트
https://paddre.tistory.com/214

 

viewBinding도 좋지만, 머기업에서 사용하는 MVVM 패턴을 적용하기 위해 dataBinding도 익숙해지게 공부 할 필요가 있어보인다. 지금까지 한게 기초중의 기초라니.. 말도ㅇ ㅏㄴ돼..

 

 

 

 

 

728x90
반응형