ViewBinding
ViewBinding을 사용하면 각 XML 레이아웃 파일의 Binding 클래스가 자동으로 생성됩니다.
Binding 클래스의 인스턴스를 통해 상응하는 레이아웃의 모든 뷰를 직접 참조할 수 있습니다.
- Null 안정성 : 유효하지 않은 id를 사용하는 null exception를 방지할 수 있습니다.
- Type 안정성 : view 타입을 잘못 캐스팅하는 cast exception를 방지할 수 있습니다.
- 속도 : findViewById()보다 빠릅니다.
ViewBinding 사용하기
1. build.gradle에 추가
viewBinding{
enabled = true
}
// Android Studio 버전 4.0 이상
buildFeatures {
viewBinding = true
}
2. Activity에서 ViewBinding 사용
레이아웃 파일명이 activity_main라면 바인드 클래스명은 ActivityMainBinding이 됩니다.
inflate()는 XML 파일을 읽어와 해석하는 역할을 하는데 이 과정에서 layoutInflater가 필요합니다.
여기서 LayoutInflater는 레이아웃 XML 파일을 통해 View 객체를 실체화해주는 역할을 합니다.
이렇게 생성된 viewBinding의 루트 뷰를 setContentView()에게 넘겨주면 해당 액티비티에 표시됩니다.
private lateinit var viewBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(viewBinding.root)
viewBinding.textView.text = "Hello World!"
viewBinding.button.setOnClickListener { /* ... */ }
}
3. Fragment에서 ViewBinding 사용
Fragment에서 ViewBinding을 사용하려면 onCreateView() 메서드에서 다음을 수행합니다.
- 생성된 Binding 클래스에 포함된 inflate() 메서드를 호출하여 Binding 클래스 인스턴스를 생성합니다.
- getRoot() 메서드를 호출해서 root View 참조를 가져옵니다.
- onCreateView() 메서드에서 root View를 리턴해서 화면 활성 뷰로 만듭니다.
// 처음에 null로 값 할당
private var _binding: FragmentFirstBinding? = null
// onCreateView()와 onDestroyView() 사이에서만 유효함
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentFirstBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.textView.text = "안녕"
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
- 처음에 _binding을 null로 할당해주는 것
- onCreateView()와 onDestroyView() 사이에서만 유효한 binding을 따로 선언해주는 것
- onDestroyView()에서 _binding을 다시 null로 초기화해주는 것
위의 과정을 수행하는 이유는 View보다 더 오래 살아남는 Fragment의 생명주기 때문입니다.
Binding 클래스는 View에 대한 참조를 가지고 있는데 View가 제거될 때 이 Binding 클래스의 인스턴스도 같이 정리해 주어야 합니다.
DataBinding
DataBinding은 UI 요소와 데이터를 프로그램적 방식으로 연결하지 않고, 선언적 형식으로 결합할 수 있게 도와주는 라이브러리를 말한다.
- 프로그램적 방식 : 코드 상에서 뷰에 연결해 값 할당
- 선언적 형식 : 레이아웃 파일에서 직접 뷰에 값 할당
DataBinding 사용하기
1. build.gradle에 추가
dataBinding{
enabled = true
}
// Android Studio 버전 4.0 이상
buildFeatures {
dataBinding = true
}
2. <layout> 태그 안에 XML 레이아웃 작성
DataBinding을 사용하는 XML 리소스는 <layout> 태그로 시작하여야 합니다.
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/nameTextView"
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" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
3. Activity에서 기존의 setContentView()를 DataBindingUtil.setContentView()로 교체
기존의 setContentView()를 DataBindingUtil.setContentView()로 대체함으로써 DataBindingUtil 클래스의 객체를 생성합니다.
private lateinit var dataBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
dataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
}
4. View에 보여줄 Data Class 선언
data 객체를 View와 binding 하기 위해서 Data Class를 하나 만들어줍니다.
package com.example.databinding.model
data class User(
val name: String,
val age: Int,
)
5. <layout> 태그 안에 <data> 요소 작성
<data> 태그는 <layout>에서 사용할 데이터를 정의하는데 사용됩니다.
<data> 태그 안에 <variable> 태그를 추가하여 데이터와 뷰를 연결합니다.
- name : 사용할 이름
- type : 연결할 데이터의 위치
레이아웃 내의 표현식은 "@{'XML에서 선언한 이름'.'설정할 데이터 속성'}" 구문을 사용하여 작성합니다.
다음과 같이 TextView의 텍스트를 user 변수의 name 속성으로 설정합니다.
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="user"
type="com.example.databinding.model.User" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.name}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
6. Activity에서 User 객체 초기화
User 객체를 초기화하여 binding 객체의 데이터에 할당해줍니다.
private lateinit var dataBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
dataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val user = User("홍길동", 30)
dataBinding.user = user
}
DataBinding 사용 이유
- findViewById()를 쓰지 않아도 자동으로 XML에 있는 View들을 만들어 줍니다.
- 데이터가 바뀌면 자동으로 바뀐 데이터로 View를 변경하게 할 수 있습니다. (Observable 사용 시)
- RecyclerView에 각각의 item을 set 해주는 작업도 자동으로 진행됩니다.
- XML에 데이터를 binding 하여 불필요한 코드를 줄일 수 있습니다.
DataBinding은 보통 MVVM 패턴을 구현할 때 사용됩니다.
BindingAdapter를 이용하면 ImageView에 이미지 로딩 라이브러리를 이용해서 이미지 출력을 쉽게 할 수 있고, LiveData를 사용하면 Data가 실시간으로 변경될 때 View도 같이 변경되어 MVVM 패턴 구현 시 편리해집니다.
DataBinding vs ViewBinding
DataBinding은 ViewBinding의 역할도 수행하면서, 추가로 동적 UI 콘텐츠를 선언할 수 있고 양방향 DataBinding도 지원합니다.
반면에, ViewBinding은 DataBinding보다 퍼포먼스 효율이 좋고 용량이 절약되는 장점이 있습니다.
따라서, MVVM 아키텍처과 함께 사용하여 DataBinding을 사용하는 것이 아니라 단순히 findViewById()를 대체하기 위해 Binding을 쓰는 것이라면 ViewBinding 사용을 권장합니다,
'안드로이드 > 개념' 카테고리의 다른 글
[Android] 정규표현식 (0) | 2023.10.11 |
---|---|
[Android] LiveData (0) | 2023.10.09 |
[Android] Touch (0) | 2023.10.06 |
[Android] @JvmOverloads (0) | 2023.08.06 |
[Android] Broadcast Receiver (0) | 2023.08.01 |