이전에는 안드로이드 코드단에서 view의 컴포넌트들을 객체로 만들어 사용하고 컨트롤하기 위해서 findViewById()
메소드를 많이 사용했었습니다.
val textView = findViewById<TextView>(R.id.tv_id)
위 코드와 같이 뷰를 참조하기 위해 findViewById()
메소드를 이용하는 방법은 몇 가지 문제가 있습니다.
이러한 findViewById()
를 대체하고 문제점들을 해결하기 위해 viewBinding
이 등장하게 됩니다.
viewBinding
은 뷰의 컴포넌트를 객체화시키지 않고 바로 사용할 수 있어 불필요한 코드 작업을 줄입니다.
findViewById()
와의 비교module 수준의 build.gradle에서 viewBinding
사용을 설정합니다.
android {
...
viewBinding {
enabled = true
}
}
위의 설정을 완료하면 각 XML 레이아웃 파일마다 binding class가 생성됩니다.
예시로 user_info.xml
레이아웃 파일이 있고, 그 파일의 코드는 아래와 같습니다.
<LinearLayout ... >
<ImageView android:cropToPadding="true" />
<TextView android:id="@+id/tv_id" />
<Button android:id="@+id/bt_save" />
</LinearLayout>
UserInfoBinding
이 되고, 자동으로 id가 존재하지 않는 ImageView를 제외한 TextView와 Button의 참조를 가지게 됩니다. getRoot()
메소드를 가집니다. 예시의 경우 getRoot()
메소드는 LinearLayout을 리턴하게 됩니다. // 1. lateinit 예약어를 사용해 선언
private lateinit var binding: UserInfoBinding
// 2. activity의 onCreate() 메소드에서 생성
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
// 3. inflate() 메소드를 호출해 인스턴스 생성
binding = UserInfoBinding.inflate(layoutInflater)
// 4. getRoot() 메소드를 호출해 root view 참조를 가져옴
val view = binding.root
// 5. root view를 setContentView()에 전달해 화면상의 활성 뷰로 만들기
setContentView(view)
}
이제 binding class의 인스턴스를 사용해 view 참조가 가능합니다.
binding.tvId.text = viewModel.name
binding.btSave.setOnClickListener { viewModel.userClicked() }
// 1. fragment binding class를 null로 초기화
private var _binding: UserInfoBinding? = null
private val binding get() = _binding!!
// 2. onCreateView() 메소드에서 binding class 인스턴스 설정하기
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// 3. inflate() 메소드를 호출해 인스턴스 생성
_binding = UserInfoBinding.inflate(inflater, container, false)
// 4. getRoot() 메소드를 호출해 root view 참조를 가져옴
val view = binding.root
// 5. root view를 리턴해 화면상의 활성 뷰로 만들기
return view
}
// 6. binding class를 null 처리
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
이제 위의 Activity에서의 사용
에서 설명한 것과 같이 binding class의 인스턴스를 사용해 view 참조가 가능합니다.
⚠️ 주의할 점
프래그먼트는 뷰보다 수명이 깁니다.
-> 따라서 프래그먼트의 lifecycle에서 뷰가 제거될 때 호출되는 onDestroyView()
콜백 메소드에서 binding class의 인스턴스를 null 값으로 변경하여 참조를 정리해주어야 합니다.
dataBinding
은 Android JetPack 라이브러리 중 하나로 xml 레이아웃 파일에 data를 결합해 findViewById()
메소드를 사용하지 않아도 되고, 결합된 데이터가 변할 때 view에 변경된 데이터를 쉽게 반영할 수 있는 장점이 있습니다.
LiveData
와 함께 많이 쓰입니다.viewBinding
과 같이 뷰를 직접 참조하는데 사용 가능한 binding class를 제공합니다.viewBinding
과 dataBinding
은 서로 비교했을 때, 각각의 이점을 가지고 있습니다.
dataBinding
의 경우, xml 레이아웃 파일에 따로 tag 처리를 해주어야 하지만 viewBinding
은 그러한 과정이 필요하지 않기 때문에 사용이 편리합니다.viewBinding
과 dataBinding
을 통해 뷰를 참조하는 방법을 사용해보니, 이전에 findViewById()
메소드를 사용해 뷰를 참조했을 때보다 훨씬 더 편리하고 안전하게 코드를 짤 수 있었습니다.viewBinding
과 dataBinding
중 무조건 하나만 골라 사용하기 보다는 상황에 따라서 적절한 바인딩 방법을 선택해 사용하는 것이 좋은 방법인 것 같습니다.