heylo 2025. 4. 9. 14:59

ViewBinding

counter 구현 시, UI 요소를 가져올때 findViewByID 를 사용했었다.

이번에는 viewBinding 을 사용해볼 것이다.

viewBinding은 findViewByID 를 대체한다.

 

 


1) findViewByID 와 ViewBinding

1-1) findViewByID

뷰의 id 값은 한 파일 내에서는 유일하지만

여러 파일 범위에서는 유일하지 않다.

 

 

activity_main 이 아닌 다른 xml 파일에서도

textView 를 id 로 하는 뷰를 생성할 수 있다.

따라서 id 가 중복이 되는 이슈가 있다.

 

 

main_activity.xml 이 아닌

second_activity.xml 에 textView 를 생성하자.

 

그리고 MainActivity.kt 에서 아래와 같은 코드를 작성하고 Run 한다.

val textView = findViewById<TextView>(R.id.textView)
textView.text = "안녕하세요."

 

Run 결과, 아래와 같이 앱이 crash 가 난다.

Activity 를 시작할 수 없고, 그 이유는 NullPointException 이라는 오류가 발생.

reference 할 object 가 없기 때문에 setText 를 할 수 없다.

 

정확히 아래 부분에서 에러가 발생했다고 알려주지만

빨간줄이 쳐져있지 않은 것을 보아

컴파일 단계에서 디버깅이 되지 않았다.

 

textView 는 R 파일에 id 로 선언이 되어 있지만

activity_main 이라는 xml 에 선언되어있는 UI 요소가 아니다.

따라서 접근이 불가능하다.

id 값으로 UI 요소를 가져오면, 위와 같은 위험요소가 발생한다.

 

 


1-2) ViewBinding

반면, viewBinding 을 사용하면?

선언했던 UI 요소를 바로 가져올 수 있다.

선언하지 않은 UI 요소들은 뜨지도 않는다.

 

 

장점

findViewByID 에서 발생할 수 있는 NPE 를 방지하고

UI 요소 값을 기억하지 않고도 바로 쉽게 가져올 수 있다.

 

 


2) 사용 순서

2-0) gradle 파일에 viewBinding 사용 선언.

2-1) binding 변수를 선언하여, layoutInflator 로 view를 생성한 후

2-2) view 를 가져와 변수에 담는다.

2-3) setContentView 로 view 세팅.

inflate : 불러 일으키다. 터트리다. 화면을 만들겠다.

binding 변수의 layoutInflater 가 뷰를 생성한다.

 


2-0) gradle : app

android { } 이하 수준에서

viewBinding 을 사용하겠다고 선언하자.

viewBinding {
        enabled = true
    }

그래들 파일을 수정하게 되면

프로젝트가 그래들 파일과 sync 를 맞춘 이후로

그래들 파일이 변경되었으므로, Sync Now 를 클릭한다.


2-1) binding 변수 선언

binding 을 변수로 선언하자.

activity class 에서만 사용할 것이니 private 으로.

 

viewbinding 을 사용하겠다고 하면,

레이아웃을 생성함과 동시에

레이아웃의 이름에 따라 binding class 가 자동으로 생성된다.

 

activity main 이라고 이름을 정했으므로

ActivityMainBinding 이라는 클래스가 자동 생성된다.

 

 

아래와 같이 코드를 작성하면

   	// 바인딩 변수 선언
    private var binding : ActivityMainBinding
    {

    }

ActivityMainBinding 이 초기화가 되어야한다는 오류가 발생한다.

 

 

따라서 나중에 초기화 하겠다는 lateinit 을 설정한다.

lateinit 설정 시, type 을 반드시 지정해주어야 한다.

// 바인딩 변수 선언
private lateinit var binding : ActivityMainBinding

 


2-2) view 가져오기

val view = binding.root

activity_main layout의 가장 상단에 있던 부모 레이아웃이

ConstraintLayout 이었음을 재확인할 수 있다.


2-3) setContentView

setContentView 로 view 를 셋팅한다.

setContentView(view)


전체코드

package com.part1.chapter3

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import com.part1.chapter3.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    // 바인딩 변수 선언
    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // binding 변수에 instance 할당
        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

//         id 값은 유일하지 않다.
//         activity_main 이 아닌 다른 xml 파일에서도
//         outputTextView 를 id 로 하는 뷰를 생성할 수 있다.
//         따라서 id 가 중복이 되는 이슈

        val outputTextView = binding.outputTextView
        val outputUnitTextView = binding.outputUnitTextView
        val inputEditText = binding.inputEditText
        val inputUnitTextView = binding.inputUnitTextView
    }
}