본문 바로가기

ANDROID - KOTLIN

[ANDROID - Kotlin] view binding 사용하기 (findViewById 없이 뷰 사용하기)

코틀린에 extension이 2021년 이후 사용할 수 없게 되면서

구글은 view binding을 사용하라고 명시 하였다.

 

따라서 오늘의 강좌는

findViewById 없이 뷰 사용하기!

해당 방법은 JAVA와 Kotlin 모두 이용한 방법이다.

(자세한 사항은 Android Developer 공식문서 를 참고해주세요!)

 

1. viewBinding 요소를 build.gradle 파일에 복사합니다.

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

 

2. 활동에서 뷰 결합 사용

 

모듈에 뷰 결합을 사용하도록 설정되면 모듈에 포함된 각 XML 레이아웃 파일의 결합 클래스가 생성됩니다. 각 결합 클래스에는 루트 뷰 및 ID가 있는 모든 뷰의 참조가 포함됩니다. 결합 클래스의 이름은 XML 파일의 이름을 카멜 표기법으로 변환하고 끝에 'Binding'을 추가하여 생성됩니다.

예를 들어 레이아웃 파일 이름이 activity_main.xml이 아래와 같이 작성되어 있다면,

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/first_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="버튼입니다!"/>

    <TextView
        android:id="@+id/first_textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="텍스트 뷰 입니다.!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</LinearLayout>

생성된 결합 클래스 이름은 ActivityMainBinding이 됩니다. 이 클래스에는 first_button이라는 Button과 first_textview라는 TextView 등 두 필드가 있습니다. 레이아웃의 ImageView에는 ID가 없으므로 결합 클래스에 참조가 없습니다.

 

또한 모든 결합 클래스에는 상응하는 레이아웃 파일의 루트 뷰에 관한 직접 참조를 제공하는 getRoot() 메서드가 포함됩니다. 이 예에서는 ActivityMainBinding 클래스의 getRoot() 메서드가 LinearLayout 루트 뷰를 반환합니다.

 

3. 사용

    private lateinit var binding: ActivityMainBinding


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }

결합 클래스 인스턴스를 사용하여 뷰를 참조할 수 있습니다.

        binding.firstTextview.text = "안녕하세요 choi 입니다."

 

layout에서는 first_textview로 지정하였지만 자동으로 카멜케이스로 변환하여 참조하도록 해준다.

 

*만약 프레그먼트에서 view binding을 사용하려면 아래의 방법을 참고해야한다.

 

프래그먼트에서 뷰 결합 사용

    private var _binding: ActivityMainBinding? = null
    
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = ActivityMainBinding.inflate(inflater, container, false)
        val view = binding.root
        return view
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
    
    binding.firstTextview.text = "안녕하세요 choi 입니다."

 

 

아래의 내용은 개발 문서에서 가져왔다.

findViewById와의 차이점

뷰 결합에는 findViewById를 사용하는 것에 비해 다음과 같은 중요한 장점이 있습니다.

  • Null 안전: 뷰 결합은 뷰의 직접 참조를 생성하므로 유효하지 않은 뷰 ID로 인해 null 포인터 예외가 발생할 위험이 없습니다. 또한 레이아웃의 일부 구성에만 뷰가 있는 경우 결합 클래스에서 참조를 포함하는 필드가 @Nullable로 표시됩니다.
  • 유형 안전: 각 바인딩 클래스에 있는 필드의 유형이 XML 파일에서 참조하는 뷰와 일치합니다. 즉, 클래스 변환 예외가 발생할 위험이 없습니다.

이러한 차이점은 레이아웃과 코드 사이의 비호환성으로 인해 런타임이 아닌 컴파일 시간에 빌드가 실패하게 된다는 것을 의미합니다.