[Jetpack AAC] View Binding 정리
핵심 : findViewById 를 쓰지 않는다.
뷰 바인딩은 각 XML 레이아웃 파일에 해당하는 바인딩 클래스(Binding Class)를 자동 생성하여 뷰에 대한 직접 참조를 가능케 한다. 기존에는 코틀린 합성 프로퍼티를 이용해서 했지만 코틀린 합성 프로퍼티는 이제 deprecated 예정이기에 공식적으로 이 방법을 쓰는게 맞다.
기본적인 뷰바인딩 사용방법과 3가지 사례(Activity에서 사용법, Fragment에서 사용법, ViewHolder에서 사용법)를 정리해보겠다.
준비
- 안드로이드 스튜디오 3.6 이상 (Canary 11 이상) 에서 사용 가능
- 모듈 수준 gradle 파일에 다음을 추가한다.
android{
... 중략
viewBinding {
enabled = true
}
}
이렇게 해도된다
android{
...
buildFeatures {
viewBinding true
}
}
이렇게하면 우리는 액티비티에서 다음 클래스를 참조할 수 있다.
예를 들어 MainActivity 라는 클래스가 있고 이 레이아웃 파일이 activity_main.xml 이라면 다음과 같은 클래스가 자동 생성되어 참조할 수 있다.
내가 구성한 XML 파일 : activity_main.xml
자동 생성된 바인딩 클래스 : ActivityMainBinding.class
즉 자동 생성되는 이름 규칙은 _(언더바)를 기준삼아 카맬 표기법으로 생성된다. 이건 android 탐색창에서 나타나지 않는 클래스이다. (위와 같은 클래스를 만들라는게 아니다. 저건 자동 생성되는 것)
이런 규칙은 xml 레이아웃 파일 내에 뷰 id 에도 적용된다. 예를들어 android:id="@+id/button_back" 이라고 내가 아이디를 설정해 놓았다면, buttonBack 이라는 참조가 자동 생성된다. (뷰에 대해선 첫 글자가 소문자, 알 필요 없다. 자동생성이니깐!)
액티비티(Activity)에서 사용법
보통 다양한 변형이있는데, 결국 다 똑같은 코드이다. 제일 모범 답안을 고르라면 난 구글에서 제시하는 코드랩 예시를 고르겠다. XML 레이아웃에서 Back 버튼을 구현하기 위한 버튼 뷰가 있다고 가정하고, 아이디가 다음과 같을 떄
android:id="@+id/button_back"
아래와 같이 클릭 리스너를 붙이면 아주 Fancy 하다.
class MainActivity : AppCompatActivity() {
private val binding by lazy(LazyThreadSafetyMode.NONE){
ActivityMainBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setConetentView(binding.root)
binding.buttonBack.setOnClickListener { onBackPressed() }
}
}
binding 상수는 XML 바인딩 클래스를 참조하는 변수로 이제부터 이 변수를 통해 뷰에 대한 접근을 시도할 수 있다.
프래그먼트(Fragment)에서 사용법
PlayerFragment 라는 클래스가 있고, 이 레이아웃을 fragment_player 가 표현하고 있다고 가정하자. 그럼 다음과 같이 바인딩 할 수 있다.
class PlayerFragment : Fragment() {
private lateinit var binding: FragmentPlayerBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View{
binding = FragmentPlayerBinding.inflate(inflater)
return binding.root
}
}
이렇게 해도 된다.
class PlayerFragment : Fragment(R.layout.fragment_player) {
private var binding: FragmentPlayerBinding? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val fragmentPlayerBinding = FragmentPlayerBinding.bind(view)
binding = fragmentPlayerBinding
}
뷰홀더(ViewHolder)에서 사용법
안드로이드 개발을 하다보면 리사이클러뷰(RecyclerView) 등 각종 뷰 홀더를 쓸 일이 정말 많다. 여기서도 바인딩하는 법을 알아보면 다음과 같다. 리사이클러뷰에 들어갈 아이템은 item_raw.xml 파일에 레이아웃을 구성했다고 가정하면 다음과 같이 ItemRowBinding 이라는 바인딩 클래스를 이용하여 참조할 수 있다.
class ViewAdapter(var dataList:Array<DataModel>)
: RecyclerView.Adapter<ViewAdapter.MyViewHolder>(){
inner class MyViewHolder(var binding : ItemRowBinding) : RecyclerView.ViewHolder(binding.root){
fun bind(position:Int){
binding.txtMusicName.text = dataList[position].name
binding.txtMusicTime.text = dataList[position].time
binding.btnMusicControl.setOnClickListener {
.. 클릭 구현
}
}
}
// 바인딩
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
var binding = ItemRowBinding.inflate(LayoutInflater.from(parent.context),parent,false)
return MyViewHolder(binding)
}
override fun getItemCount(): Int = dataList.size
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(position)
}
...
여기서 난 생성자에 Array를 넘겨줬지만 이는 다르게 구현해도 된다. 이것은 리사이클러뷰 구현 스타일 차이이므로 이번 포스트에서 다룰 내용이 아니다.
리사이클러뷰를 구현해본 적이 있다면 위 코드로 충분히 참고가 될 것 같다.
나는 바인딩 클래스를 자동 생성하기 싫다
특정 XML 파일에 대해서는 바인딩클래스를 생성하지 않고 싶은 경우가 있다. 그런 경우에는 XML 파일의 루트 뷰에 다음과 같은 속성을 추가해주면 된다.
<LinearLayout
...
tools:viewBindingIgnore="true" >
...
</LinearLayout>
Reference
https://developer.android.com/topic/libraries/view-binding
끝.
'Mobile : Android > Jetpack' 카테고리의 다른 글
[Jetpack AAC] 뷰모델(ViewModel) #1 : MVVM (0) | 2022.06.13 |
---|---|
[Jetpack AAC] Data Binding 기본 #2 : ObservableField (0) | 2022.04.30 |
[Jetpack AAC] Data Binding 기본 #1 (0) | 2022.04.12 |
[Jetpack Compose] Compose # 1 - 기본 (0) | 2021.11.06 |
댓글