데이터 바인딩은 단순히 데이터를 결합하는 것뿐만 아니라 표현식으로 데이터를 가공하거나 메서드 참조와 리스너를 결합하여 별도의 호출코드 없이 사용할 수 있습니다.
표현식 언어
일반적인 기능
표현식 언어는 관리형 코드에서 볼 수 있는 표현식과 매우 비슷합니다.
산술 | +, -, /, *, % |
문자열 연결 | + |
논리 | &&, || |
바이너리 | &, |, ^ |
단항 | +, -, !, ~ |
전환 | >>, >>>, << |
비교 | ==, >, <, >=, <=, (<는 ⁢ 으로 이스케이프 처리 해야함) |
instanceof | |
그룹화 | () |
리터럴 | 문자, 문자열, 숫자, null |
변환 | |
메서드 호출 | |
필드 액세스 | |
배열 액세스 | [] |
삼항 연산자 | ?: |
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'
간단한 예로 위 코드처럼 @{} 내에서 표현식을 사용할 수 있습니다.
표현식의 단점으론 디버깅이 힘들어집니다.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(NullPointerException)}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
텍스트 뷰에서 의도적으로 에러를 일으켜봤습니다.
/Users/hwan/AndroidStudioProjects/DatabindingTest/app/build/generated/ap_generated_sources/debug/out/com/bind/databindingtest/databinding/ActivityMainBindingImpl.java:95: error: cannot find symbol
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView1, java.lang.String.valueOf(java.lang.NullPointerException));
^
symbol: class lang
location: package java
자동 생성되는 BindingImpl에서 에러가 나는 것을 볼 수 있습니다. 별도의 연산이 필요하다면 코드에서 하는 게 낫습니다.
누락된 연산자
표현식 구문에서 누락된 연산자는 다음과 같습니다.
- this
- super
- new
- Generic 호출
Null 병합 연산자
null 병합 연산자('??')는 ?? 기준으로 왼쪽이 null이 아니면 왼쪽을 선택하고 null이면 오른쪽을 선택합니다
data class Ddd(
var firstValue: String?,
var secondValue: String
)
fun databinding(){
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.lifecycleOwner = this
binding.ddd = Ddd(null, "ddd")
}
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{ddd.firstValue ?? ddd.secondValue}"
...
</TextView>

firstValue가 null이기 때문에 secondValue가 선택된 모습을 볼 수 있습니다. 연산은 삼항 연산자와 같습니다
뷰 참조
표현식에서 ID를 이용하여 레이아웃의 다른 뷰를 참조할 수 있습니다.
<LinearLyaout
...
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{edit.text}" />
<EditText
android:id="@+id/edit"
android:layout_width="50dp"
android:layout_height="wrap_content" />
</LinearLyaout>
텍스트뷰에서 에딧 텍스트의 값을 참조하는 코드입니다.

입력된 값이 텍스트뷰로 바로 나오는 것을 볼 수 있습니다.
컬렉션
리스트나 맵, 배열과 같은 일반 컬렉션에는 코드에서 쓰는 것처럼 [] 연산자를 이용해서 액세스 할 수 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<import type="java.util.List"/>
<variable
name="ddd"
type="List<String>" />
<import type="android.Manifest.permission" />
</data>
<LinearLayout
...>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{ddd[0]}" />
<TextView
android:id="@+id/edit"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:text="@{ddd[1]}"
/>
</LinearLayout>
</layout>
fun databinding(){
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.lifecycleOwner = this
binding.ddd = arrayListOf("1", "2df")
}

문자열 리터럴
xml에서 기존 방식대로 문자열 리터럴을 사용하려고 하면 제대로 동작하지 않습니다.

문자열 리터럴을 넣고싶다면 작은따옴표로 감싸거나 문자열 리터럴을 백 따옴표(`)를 입력하면 됩니다
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{"테스트값"}' />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{`테스트값`}" />
이벤트 처리
데이터 바인딩을 사용하면 뷰에서 정의한 메서드를 이벤트로 줄 수 있습니다.
버튼을 누르면 Toast 를 띄워주는 기능입니다.
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="main"
type="com.bind.databindingtest.MainActivity" />
</data>
<LinearLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{() -> main.ocListener()}" />
</LinearLayout>
</layout>
<data> 태그에 참조할 클래스를 변수로 선언해 줍니다.
이벤트 참조를 하기 위해선 람다를 사용하면 됩니다.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
databinding()
}
fun databinding(){
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.lifecycleOwner = this
binding.main = this
}
fun ocListener(){
Toast.makeText(this, "button is Pressed", Toast.LENGTH_SHORT).show()
}
}
MainActivity에 있는 함수를 쓸 것이므로 바인딩에 현재 클래스를 this로 넣어줍니다.

Toast 메시지가 나오는 것을 볼 수 있습니다.
매개변수 처리
xml에서 함수처리는 람다로 하고 있습니다. 이유는 딱 하나입니다.
간결해서
람다 표현식은 함수 리터럴입니다. 함수 리터럴이란 함수를 식으로 리턴하는 함수를 말합니다. 즉, 인터페이스를 만들고 클래스로 상속받아 익명함수를 만들어 넣지 않고 람다 표현식을 이용해서 넣는 것입니다.
고차함수와 람다에 관한 게시글은 아래 링크에 있습니다.
14. 고차함수와 람다
고차 함수 고차 함수는 함수를 파라미터로 받거나 함수를 리턴하는 함수이다. fun lock(lock: Lock, body: () -> T): T{ lock.lock() try { return body() } finally { lock.unlock() } } 위 코드를 보면 body는 함수 타입인 () -
huzit.tistory.com
람다 표현식을 사용했기 때문에 패러미터로 넘기는 부분과 실제 코드가 동작하는 부분으로 나뉩니다.
이제 어떻게 매개변수를 처리해야 하는지 예제를 통해 알아봅시다
람다에서 매개변수는 넘겨주거나 모든 매개변수를 무시할 수 있습니다.
아래 예제는 모든 매개변수를 무시하는 예제입니다.
android:onClick="@{() -> main.ocListener(`testMessage`)}"
fun ocListener(text: String){
Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
}
보시다시피 ocListener에 필요한 매개변수만 넘겨주고 있습니다.
다음 예제는 매개변수를 넘겨주는 예제입니다. onClick 메서드는 View 타입의 매개변수를 가지고 있으므로 그걸 넘겨주면 됩니다.
android:onClick="@{(view) -> main.ocListener(`testMessage`)}"
매개변수로 넣어주는 view는 <data> 태그에서 정의해줘야 합니다. 구동 자체에는 문제없지만 매개변수를 쓰기 시작하면 오류를 일으킬 수 있습니다.
android:onClick="@{(view) -> main.ocListener(view.ACCESSIBILITY_LIVE_REGION_NONE)}"
-결과-
error: cannot find symbol
위 예제처럼 <data> 태그에 정의돼있지 않은 view매개변수의 상수에 접근하려고 하면 cannot find symbol 오류를 볼 수 있습니다.
마치며
데이터 바인딩은 뷰 바인딩이 나오기 이전 데이터를 원활하게 뷰에 보여주기 위한 방법으로 만들어졌습니다. 지금은 뷰 방니딩보다 빌드 속도가 느려 MVVM을 구현할 때만 사용하지만 강력한 기능임은 확실합니다.
뷰는 보여주기 위해 작성하는 것이므로 복잡한 기능은 넣지 않는 것을 추천드립니다.
참고
레이아웃 및 결합 표현식 | Android 개발자 | Android Developers
레이아웃 및 결합 표현식 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 표현식 언어를 사용하면 뷰에 의해 전달된 이벤트를 처리하는 표현식을 작성할 수
developer.android.com
GitHub - Huzit/DataBindingTest
Contribute to Huzit/DataBindingTest development by creating an account on GitHub.
github.com
'안드로이드 > Binding' 카테고리의 다른 글
데이터 바인딩(Databinding)이란? (1) | 2023.03.09 |
---|---|
뷰 바인딩(viewBInding) (0) | 2022.06.13 |