오늘은 안드로이드 Architecture Component Library중의 하나인
DataBinding에 대해서 알아보도록 하겠습니다.
1. DataBinding
DataBinding은 androidX 즉, jetpack에 포함되어 있는 라이브러리인데요.
레이아웃에 있는 View들을 data소스들과 바인딩 해주는 역할을 합니다.
XML의 요소들을 단순히 Activity클래스에서 불러다가 쓰는 것이 아니라,
XML안에서 expression들을 사용하면서,
자체적인 로직도 가질 수 있게 되는데요.
View를 담당하는 컴포넌트들의 코드가 매우 간결해지고,
그에 따라 코드를 관리하거나 읽기가 쉬워집니다.
2. 라이브러리 셋업
특별히 implement할 것은 없구요.
아래와 같이 앱레벨의 build.gradle의 android에서
dataBinding { enabled = true } 을 추가해 주기만 하면 됩니다.
아래와 같이, buildFeatures { dataBinding true } 를 추가해 주면 됩니다.
3. data클래스 생성
view와 바인딩할 data의 클래스를 먼저 생성하도록 하겠습니다.
이 글에서는 kotlin을 사용하였는데요.
역시나 코드가 매우 간결하네요.
4. XML
4-1. layout 루트태그 생성하기
본격적으로 xml에서 작업을 하기전에 한가지 꼭 해주어야 하는 작업은,
아래 이미지와 같이 루트로 layout태그를 가지고 있어야 한다는 점 입니다.
보통은 ConstratintLayout이 root에 있는데요.
layout태그를 생성한후 그것을 layout태그안에 넣어주면 됩니다.
이렇게 layout태그를 생성해 준 다음에는 rebuild를 다시 해주는 것이 좋습니다.
그래야 밑에서 expression등을 사용할 때, 안드로이드 스튜디오의 도움을 얻을 수 있고,
Activity등에서 참조할 수 있는 바인딩 클래스가 생성되기 때문입니다.
4-2. data태그 작성하기
이제 기본적인 것이 갖추어 졌으니,
어떻게 데이터 클래스와 view를 바인딩 할 것인가를 생각해 보아야 합니다.
방법은 data 태그안에 변수(variable)을 만들어
변수를 원하는 view컴포넌트의 attribute에서 사용해 주는 것 인데요.
변수(variable)는 layout태그 밑에
아래 이미지와 같이 data태그를 만들어서 사용합니다.
type에 넣는 값은 해당 데이터모델의 패키지 위치를 적어넣어 주면 됩니다.
(layout tag사용후 rebuild가 정상적으로 되었다면, 안드로이드 스튜디오의 도움을 얻어서 쉽게 작성할 수 있습니다.
일일히 패키지주소를 적어갈 필요는 없습니다.)
아래에서는 변수 name을 사용했구요.
type은 위에서 정의한 User클래스 타입이라고 하였습니다.
4-3. xml에서 사용할 수 있는 expression
xml에서 복잡한 연산을 하는 것은 좋지 못할 것으로 생각되는데요.
간단한 expression은 안드로이드 스튜디오의 도움을 얻어 쉽게 작성할 수 있으므로,
알아두면 좋은 몇가지 expression을 살펴보도록 하겠습니다.
A. import
util클래스를 만들었다고 가정해 보겠습니다.
이럴 경우 아래와 같이 import해서, expression내에서도 StringUtil.getCapitalize와 같이 사용할 수 있습니다.
참고로 이름을 바꾸고 싶을 경우, type뒤에 alias="바꾸고 싶은 이름" 형식으로 넣어주면 됩니다.
B. 삼항 연산자
age가 13보다 크지 않으면 View를 보여주라고 하는 expression을 아래와 같이 작성해 볼 수 있습니다.
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
이 때 주의해야 할 것은 아래와 같이 View를 import해 주어야 한다는 점 입니다.
추가적으로 visibility에 대한 default값은 아래와 같이 설정 가능한데요.
gone, visible, invisible 중 하나를 값으로 넣어주시면 됩니다.
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE, default=visible}"
C. 간단한 계산식
아래와 같은 간단한 표현식도 가능 합니다.
android:text="@{String.valueOf(index + 1)}"
D. Null coalescing operator
아래는 user.displayName이 null이면 대신 user.lastName을 넣으라는 것인데요.
이러한 형식의 expression도 넣을 수 있습니다.
android:text="@{user.displayName ?? user.lastName}"
이러한 expression들은 escape에 관해서는 조금 불편한 점이 있습니다.
기본적으로 쌍따옴표("")로 둘러 쌓여있으므로, 만약 안에서 쌍따옴표를 쓰려고 한다면, 바깥을 ('') 따옴표로 바꿔줘야 하구요.
List<String>은 List<String>으로 써주어야 합니다.
5. Activity
위에서 생성한 data 클래스와 view를 바인딩하기 위해서,
라이브러리는 binding class를 layoutfile 에 기초해서 생성해 줍니다.
(위에서 layout태그 적용 후에 리빌드를 했었는데요. 이 과정을 거치면 이미 생성된 것을 볼 수 있습니다.)
이 클래스가 layout프로퍼티에 있는 모든 binding을 가지고 있습니다.
이 클래스의 파일이름을 알기 위해 파일이름이 만들어 지는 규칙을 알아야 하는데요.
만약 activity_main.xml이라면, ActivityMainBinding과 같이,
XML파일의 이름을 Pascal 케이스로 변경하고 뒤에 Binding을 붙여주면 됩니다.
(XML파일을 기준으로 합니다)
기존의 setContentView는 주석처리하고, 아래와 같이 DataBindingUtil의 setContentView를 이용해 줍니다.
이제 바인딩된 객체를 얻었는데요.
이 객체에는 xlm에서 정의했던 변수에 접근할 수 있으므로,
user라는 변수에 User객체를 넣어줍니다.
참고로, 아래와 같은 방법으로도 Binding할 수 있습니다.
그럼 아래와 같이 정상적으로 "김군"이 나온 것을 알 수 있습니다.
중요한 사실은 저희가 김군이라는 텍스트를 textView에 set한 것이 아니고,
바인딩 객체의 user변수에 User객체를 넣어주기만 했다는 사실입니다.
그만큼 Activity의 코드는 줄어 들었구요.
6. RecyclerView의 Adapter 또는 Fragment
A. RecyclerView의 Adapter
inflater만 구해서, 아래와 같이 재활용할 layout에 layout태그를 넣은다음,
빌드후에 만들어진 Bindingclass를 이용해서 Binding객체를 만들 수 있습니다.
또는 아래와 같이, DataBindingUtil클래스를 이용해 Binding객체를 만들 수도 있습니다.
B. Fragment
RecyclerView에서의 방법과 다르지 않습니다.
inflater가 인자로 주어지기 때문에, 더 쉬운편이라고 할 수 있겠네요.
return값을 보면 mBinding.root로 되어 있습니다.
원래는 주석처리된 부분과 같이 레이아웃 파일의 이름을 인자로 넣어주고, inflate해서 view를 반환해 주는데,
같자기 mBinding의 root를 반환해 주고 있습니다.
혹시 여기서 view를 return할 자리에 왜 root가 들어오는 걸까요?
아래는 getRoot메소드의 소스코드인데요.
layoutFile의 가장 바깥쪽에 있는 View, 즉 Root View를 Return해 준다고 적혀있는 부분이 있네요.
바인딩된 레이아웃 파일의 루트View를 Return받을 수 있는 방법을 제공해주고 있는 것이지요.
한가지 더 lifecycleOwner에 대해서 짚고 가 보겠습니다.
Activity의 경우, lifecycleOnwer = this라고 정의했었는데요.
fragment의 경우에는 어떻게 해야할까요?
fragment클래스는 프래그먼트의 view와 fragment클래스 자신의 라이프 사이클에 차이가 생길 수 있는데요.
따라서 viewLifecycleOwner를 얻어와서 아래와 같이 사용하는 것이 좋습니다.
참고로 getLifecycleOwner함수에 대한 공식문서의 설명을 보면 아래와 같은데요.
왜 this가 아닌 viewLifecycleOwner를 사용해야 하는지에 대한 좀더 자세한 설명이 나와있네요.
6. 정리
이렇게 해서 DataBinding의 기본적인 부분에 대해서 정리하였구요.
다음 part2글에서는 Glide같은 라이브러리사용을 위한 Binding Adapter사용법이나,
EditText에서의 Listener Binding 에 대해서 정리해 보도록 하겠습니다.
'Android 개발 > Architecture 라이브러리' 카테고리의 다른 글
LifeCycle과 ViewModel 그리고 LiveData에 대해 정리해 봅니다 (0) | 2021.09.24 |
---|---|
DataBinding에 대해서 알아보자 part2(Glide, EditText) (0) | 2019.12.23 |
LiveData와 Realm 그리고 ViewModel을 같이 이용하는 방법 (0) | 2019.10.14 |
ViewModel에서 Coroutine을 이용하는 방법 #ViewModel Scope (0) | 2019.10.10 |
댓글