View Binding은 뷰와 상호작용하는 코드를 쉽게 작성할 수 있도록 만들어 주는 기능입니다.
모듈에서 View Binding을 사용하도록 설정하면 모듈에 있는 XML
레이아웃 파일들의 바인딩 클래스가 생성됩니다. 이 바인딩 클래스의 인스턴스에는 해당 레이아웃에서 ID를 가지고 있는 모든 뷰와 루트 뷰의 직접 참조가 포함되어 있습니다. 그래서 대부분의 경우 View Binding은 findViewById
를 대체할 수 있습니다.
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가 없어도 바인딩 클래스를 통해 직접 접근할 수 있습니다.
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@Nullable
로 마크하여 참조 실수를 방지할 수 있게 해줍니다. XML 파일
에서 참조하는 뷰의 타입과 일치합니다. 즉, 클래스 변환 예외가 발생할 위험이 없습니다.Null Safety
하고 Type Safety
하기 때문에 레이아웃과 코드 사이의 비호환성이 발생하면 findViewById
와 달리 런타임이 아닌 컴파일 타임에 예외를 탐지할 수 있습니다. View Binding과 Data Binding 모두 뷰를 직접 참조하는데 사용할 수 있는 바인딩 클래스를 생성합니다. 다만, View Binding은 보다 단순한 경우에 사용합니다.
XML
에 태그를 추가할 필요없고, 사용 설정하면 모든 레이아웃에 View Binding이 자동 적용되기 때문에 편리합니다. XML
레이아웃 파일에서 직접 동적 UI 컨텐츠를 선언하는데 사용할 수 없습니다.