recyclerView와 dataBinding 같이 사용하기

2021. 1. 3. 15:04android

1. dataBinding이란?


데이터 바인디이란, 레이아웃에서 선언한 구성요소를 데이터소스와 결합시켜 주는 객체를 자동으로 생성해주는 것을 의미합니다.

2. dataBinding을 사용하는 이유


xml에서 선언한 view들을(textView,editText,Button..etc..) 클래스에서 접근하려면, 기본적으로 view들에게는 모두 id값들을 적용하고, 이를 클래스에서 findViewById() 메서드를 통해서 일일히 연결시켜줘야 했습니다.

하지만 이는 공부용으로 간단한 프로젝트를 할 때에는 큰 문제가 없을지 모르나, 협업을 하는 정도의 큰 규모의 프로젝트를 진행하게 되면 여간 귀찮은 일이 아닙니다.. 또한 연결시켜주는 것만으로도 onCreate()메서드가 매우 길어집니다.

또한 한가지라도 연결을 하지 않으면 에러가 날 수 있음으로 실수할 확률도 매우 높아지게 됩니다.

이러한 문제들을 해결하기 위해 dataBinding이나 viewBinding을 사용하면 id갖는 view들을 결합시켜주는 binding 클래스를 생성하여 findViewByid()메서드를 사용하는 일이 없도록 만들어줍니다. (여기서는 dataBinding만 다루도록 하겠습니다.) 이렇게 되면 개발자가 일일히 연결시켜주지 않게되므로 실수할 확률은 현저하게 줄어들 것입니다!

3. dataBinding 사용방법


바인딩 클래스를 사용하기 위해서는 클래스의 이름을 알아야겠죠? 기본적으로 바인딩 클래스는 개발자가 만든 layout의 이름을 카멜기법으로 재조합하여 이름을 정합니다. 예를들면, R.layout.activity_main 이란 layout이 있다면 이는 카멜 표기법에 의해 ActivityMain으로 만들어지고 뒤에 Binding이 붙은 ActivityMainBinding으로 바인딩 클래스가 생성됩니다. 따라서 ActivityMainBinding을 객체화하면 xml에 id option을 갖는 view들에 바로 접근할 수 있게 됩니다!!

단, xml을 생성할 때 가장 최상위의 태그는 viewGroup이(LinearLayout,ConstrintLayout..etc..) 아닌,

태그로 감싸져야 이를 컴퓨터가 인식할 수 있습니다. 아래의 코드처럼 말이죠

4. binding class 객체화


xml에서 태그로 감싸줬다면 이젠 해당 레이아웃을 view로 객체화하는 일만 남았습니다. dataBinding이나 viewBinding을 사용하기 전까지는 레이아웃을 그대로 객체화 시켜줬다면, 이번엔 바인딩 클래스를 가지고서 객체화 시켜줘야 합니다.

이를 진행하기 위해서는 DataBindingUtil 클래스를 이용하게 됩니다. 정확하게는 DataBindingUtil.setContent()를 이용하여 binding 클래스를 객체화합니다!

5. 리싸이클러뷰와 데이터바인딩 


이번엔 리싸이클러뷰와 데이터바인딩을 같이 써보겠습니다. 위에서 같이 봤듯이 가장 먼저 해야할 일은 레이아웃에서 사용할 view들을 정의하고 이를 태그로 감싸줘야합니다.

제가 만든 main layout은 editText에 텍스트를 입력하고 버튼을 클릭하면 리싸이클러뷰에 추가되도록 만들겠습니다.

그럼 참조를 위해 필요한 id들은 recyclerView, editText, button이므로 각각 id를 설정해야합니다.

 

 

그리고 해당 바인딩 클래스를 MainActivity에서 객체화 해주면 이제 binding이란 객체를 통해서 recyclerView, button, edittext등 id를 설정한 view들로 접근할 수 있게 됩니다.

 

 

이번엔 리싸이클러뷰에 들어갈 아이템 레이아웃을 정의해 보겠습니다. 해당 레이아웃의 구성은 editText에서 입력한 텍스트를 화면상에 보여주기 위해서 textview하나만 있으면 됩니다. 물론 저는 CardView로 textview로 감싸서 한 층 ui에 신경써봤습니다^^

 

 

리싸이클러뷰는 어댑터를 통해 아이템을 하나하나 배치합니다. 그러므로 우리가 정의한 talk_balloon_item layout은 리싸이클러뷰 어댑터에서 정의가 됩니다!! 이는 dataBinding을 사용할 때나 안했을 때나 같습니다! 다만 dataBinding을 사용한 방식으로 정의하는게 다른 뿐이죠.

 

 

어댑터의 구성중에 가장 중요한 부분은 당연히 onCreateViewHolder()입니다. 해당 메서드에서는 우리가 정의한 item layout를 바인딩 객체화 시켜주는 부분이기 때문입니다. 그런 해당 부분은 액티비티에서 객체화한 방식과는 조금 다릅니다.

액티비티에서는 setContent()메서드로 바로 view 객체화 시켜주었다면, 어댑터에서는 infalte()를 사용하여 view객체화 시켜주기 때문입니다. 그런데 dataBinding을 사용하지 않았을 때도 inflate를 통해 객체화 시켜주었음으로 DataBindingUtill 클래스를 통해서 inflate한다는 걸 제외하곤 똑같습니다.

그리고 또 한가지 다른점은 뷰홀더의 파라미터로는 바인딩클래스를 받는다는 것입니다. 기존에는 view를 받았겠지만 저는 바인딩 객체를 받아서 RecyclerVIew.ViewHolder에 바인딩 객체의 root를 사용하여 view객체를 넘겨줍니다. 이는 제가 커스텀한 것이니, 바인딩객체를 파라미터로 사용하지 않고 view를 받는 파라미터로 설정해도 상관없습니다!

마지막으로 addItem()메서드는 액티비티의 editText에서 입력한 내용들을 어댑터에서 알기 위한 메서드입니다.

이렇게 모든 준비가 끝났다면 해당 로직을 완성하기 위해서 다시 mainActivity로 돌아가겠습니다. 다시한번 말하면 구현하고자 하는 로직은 editTextView에서 입력한 텍스트를 보내기 버튼을 통해 리싸이클러뷰에 띄우는 것입니다!!

 

 

코드를 보면 findViewById() 필요없이 binding 객체를 통해서 직접적으로 view에 접근할 수 있게 되는 것을 볼 수 있습니다.

구현한 로직을 보면 onTextChanged()를 통해서 editText에 입력한 텍스트를 실시간으로 s변수에 받아오도록합니다. 이후 submitTalk()을 통해서 어댑터에 입력한 텍스트를 보내고 갱신합니다.

ps) smoothScrollToPosition()을 사용한 이유는 리스트에 추가된 아이템이 많을 수록 화면은 스크롤이 되어집니다. 따라서 현재 자신이 친 텍스트를 보기 위해서 자동으로 스크롤이 되도록하는 기능입니다.

ps) setHasFixedSize()에서 아규먼트가 false인 이유는 리싸이클러뷰의 size가 계속 변하기 때문입니다. 만약 처음 셋팅에서 리싸이클러뷰의 size가 결정되고 item의 내용만을 변경하는 것이라면 처음 정해진 리싸이클러뷰의 size가 변경될 일이 없음으로 true로 지정하는 것이 맞습니다. 하지만 데이터를 추가하고 삭제하는 작업은 리싸이클러뷰의 size가 계속 변하게 되므로 setHasFixedSize를 false줘서 리싸이클러뷰를 다시 그려야합니다.

 

6. 결과