[Android] View Binding

Hwichan Ji·2021년 8월 30일
0

Android

목록 보기
5/7
post-thumbnail

📌 View Binding

View Binding은 뷰와 상호작용하는 코드를 쉽게 작성할 수 있도록 만들어 주는 기능입니다.

모듈에서 View Binding을 사용하도록 설정하면 모듈에 있는 XML 레이아웃 파일들의 바인딩 클래스가 생성됩니다. 이 바인딩 클래스의 인스턴스에는 해당 레이아웃에서 ID를 가지고 있는 모든 뷰와 루트 뷰의 직접 참조가 포함되어 있습니다. 그래서 대부분의 경우 View Binding은 findViewById를 대체할 수 있습니다.

모듈에서 View Binding 사용 설정

View Binding은 모듈 단위로 사용 설정되며, build.gradle 파일에 View Binding 사용 여부를 명시합니다.

// android studio 4.0 이하
android {
    viewBinding {
        enabled = true
    }
}

---------------------------

// android studio 4.0 이상
android { 
    buildFeatures { 
        viewBinding = true 
    }
}

특정 레이아웃 무시

특정 레이아웃의 바인딩 클래스를 생성하지 않으려면 tools:viewBindingIgnore="true" 속성을 루트 뷰에 추가해야 합니다.

<LinearLayout
        tools:viewBindingIgnore="true">
</LinearLayout>

바인딩 클래스

모듈에 View Binding 사용하도록 설정되면 XML 레이아웃 파일의 이름을 파스칼 표기법으로 변환하고 끝에 Binding을 추가한 이름을 가진 바인딩 클래스가 생성됩니다.

<LinearLayout ... >
        <TextView android:id="@+id/name" />
        <ImageView android:cropToPadding="true" />
        <Button android:id="@+id/btn" />
</LinearLayout>

예를 들어 레이아웃 파일 이름이 result_profile.xml인 경우 ResultProfileBinding이라는 바인딩 클래스가 생성되며, 이 클래스에는 name이라는 TextView 필드와 btn이라는 Button 필드가 있습니다. ImageView는 ID가 없기 때문에 바인딩 클래스에 참조가 존재하지 않습니다.

루트뷰 접근

모든 바인딩 클래스에는 해당 레이아웃의 루트 뷰에 관한 직접 참조를 제공하는 getRoot() 메서드가 포함되어 있습니다. 따라서 레이아웃의 루트 뷰는 ID가 없어도 바인딩 클래스를 통해 직접 접근할 수 있습니다.

View Binding 사용

Activity에서 View Binding 사용

생성된 바인딩 클래스의 inflate() 메서드를 호출하면 바인딩 클래스의 인스턴스가 생성됩니다.

인스턴스가 생성되면 getRoot() 메서드를 통해 루트 뷰 참조를 가져오고 이 루트 뷰를 onCreate()에서 setContentView() 메서드에 전달하여 레이아웃을 활성 뷰로 만듭니다.

private lateinit var binding: ResultProfileBinding

override fun onCreate(savedInstanceState: Bundle) {
    super.onCreate(savedInstanceState)
    binding = ResultProfileBinding.inflate(latoutInflater)
    val view = binding.root
    setContentView(view)
}

이후에는 인스턴스를 사용하여 뷰를 참조합니다.

binding.name.text = viewModel.name
binding.btn.setOnClickListener { viewModel.userClicked() }

Fragment에서 View Binding 사용

Activity에서 View Binding을 사용하는 것과 거의 동일하며, 활성 뷰로 만드는 부분에서만 차이가 있습니다.

Fragment에서는 onCreateView()에서 루트 뷰를 반환하여 레이아웃을 활성 뷰로 만듭니다.

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

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

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

findViewById와의 차이점

Null Safety

  • View Binding은 뷰의 직접 참조를 생성하므로 유효하지 않은 뷰 ID로 인해 Null Pointer 예외가 발생하지 않습니다.
  • 레이아웃에 포함된 뷰가 특정 조건에서만 존재하는 경우, 바인딩 클래스는 해당 필드를 @Nullable로 마크하여 참조 실수를 방지할 수 있게 해줍니다.

Type Safety

  • 각 바인딩 클래스에 있는 필드의 타입이 XML 파일에서 참조하는 뷰의 타입과 일치합니다. 즉, 클래스 변환 예외가 발생할 위험이 없습니다.

예외 탐지

  • View Binding은 Null Safety하고 Type Safety하기 때문에 레이아웃과 코드 사이의 비호환성이 발생하면 findViewById와 달리 런타임이 아닌 컴파일 타임에 예외를 탐지할 수 있습니다.

Data Binding과의 차이

View Binding과 Data Binding 모두 뷰를 직접 참조하는데 사용할 수 있는 바인딩 클래스를 생성합니다. 다만, View Binding은 보다 단순한 경우에 사용합니다.

View Binding이 더 나은 점

  • 주석 처리가 필요하지 않기 때문에 컴파일 시간이 더 짧습니다.
  • XML에 태그를 추가할 필요없고, 사용 설정하면 모든 레이아웃에 View Binding이 자동 적용되기 때문에 편리합니다.

View Binding이 더 안좋은 점

  • XML 레이아웃 파일에서 직접 동적 UI 컨텐츠를 선언하는데 사용할 수 없습니다.
  • 양방향 데이터 바인딩을 지원하지 않습니다.

Reference

profile
안드로이드 개발자를 꿈꾸는 사람

0개의 댓글