Part1_Ch03_04 UI 요소 가져오기
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
}
}