Data Binding이란?
: 프로그래밍 방식이 아니라 선언적 형식으로 레이아웃의 UI 구성요소를 앱의 데이터 소스와 결합할 수 있는 지원 라이브러리다.
- 프로그래밍 방식
findViewById<TextView>(R.id.sample_text).apply {
text = viewModel.userName
}
- Data Binding 방식
<TextView
android:text="@{viewmodel.userName}" />
Data Binding을 사용하는 이유
- Activity/Fragment에서 많은 UI 프레임워크 호출을 삭제할 수 있어 파일이 더욱 단순화되고 유지관리 또한 쉬워진다.
- findViewById를 사용할 때 발생할 수 있는 null 포인터 예외를 방지할 수 있다.
- 메모리 누수를 방지할 수 있다.
사용하기
- build.gradle(Module)에서 다음 코드를 입력해야 한다.
android {
...
dataBinding {
enabled = true
}
}
- 레이아웃 파일에서 다음과 같이 layout의 루트 태그로 시작하고 data 요소 및 view 루트 요소가 뒤따라야 한다.
- layout의 루트 태그를 클릭 후 alt + Enter를 누르면 data binding layout으로 변환할 수 있다.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout>
...
</LinearLayout>
</layout>
- <data>안에 <variable>로 이 레이아웃 내에서 사용 할 타입을 적는다.
<variable name="user" type="com.example.User" />
- '@{}' 구문을 사용하여 앱의 데이터 소스와 UI 구성요소를 결합한다.
- user.firstName은 User 클래스에 firstName 프로퍼티가 있으면 프로퍼티로 인식하고, firstName() 메소드가 있으면 메소드로 인식한다.
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}" />
- Activity에서는 (1), (2)중에 선택해서 사용한다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(getLayoutInflater()) // (1)
val binding = DataBindingUtil.setContentView(this, R.layout.activity_main) // (2)
// 레이아웃에 데이터를 할당하는 방법
binding.user = User("Test", "User")
}
- Fragment, ListView 또는 RecyclerView 어댑터에서는 (3), (4)중에 선택해서 사용한다.
val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false) // (3)
val listItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false) // (4)
표현식 언어
일반적인 기능
: 표현식 언어에서는 다음 연산자와 키워드를 사용할 수 있다.
- 산술 : +, -, /, *, %
- 문자열 연결 : +
- 논리 : &&, ||
- 바이너리 : &, |, ^
- 단항 : +, -, !, ~
- 전환 : >>, >>>, <<
- 비교 : ==, >, <, >=, <= (<는 <으로 이스케이프 처리해야 함)
- instanceof
- 그룹화 : ()
- 리터럴 : 문자, 문자열, 숫자, null
- 변환
- 메소드 호출
- 필드 액세스
- 배열 액세스 : []
- 삼항 연산자 : ?:
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'
누락된 연산자
: 다음 연산자는 사용할 수 없다.
- this
- super
- new
- 명시적 제네릭(Generic) 호출
Null 병합 연산자
: null 병합 연산자(??)는 왼쪽 피연산자가 null이 아니면 왼쪽 피연산자를 선택하고 null이면 오른쪽 피연산자를 선택한다.
android:text="@{user.displayName ?? user.lastName}" // null 병합 연산자
android:text="@{user.displayName != null ? user.displayName : user.lastName}" // 위와 기능적으로 동일
속성 참조
: 다음 형식으로 클래스의 속성을 참조할 수 있으며 이 형식은 fields, getters 및 ObservableField 객체에서도 동일하다.
android:text="@{user.lastName}"
null 포인터 예외 방지
: 자동으로 null 값을 확인하고 null 포인터 예외를 방지한다.
- @{user.name} 에서 user가 null이면 user.name에 null이 기본값으로 할당된다.
- @{user.age} 에서 user가 null이면 user.age에 0이 기본값으로 할당된다.
뷰 참조
: ID를 통해 레이아웃의 다른 뷰를 참조할 수 있다.
android:text="@{exampleText.text}" // ID는 카멜 표기법으로 변환하여 사용해야 한다.
컬렉션
: Array, List, Sparse List, Map과 같은 Collection들은 [] 연산자를 사용하여 참조할 수 있다.
<data>
<import type="android.util.SparseArray"/>
<import type="java.util.Map"/>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/> // "<"를 "<"로 이스케이프 처리
<variable name="sparse" type="SparseArray<String>"/> // "<"를 "<"로 이스케이프 처리
<variable name="map" type="Map<String, String>"/> // "<"를 "<"로 이스케이프 처리
<variable name="index" type="int"/>
<variable name="key" type="String"/>
</data>
…
android:text="@{list[index]}"
…
android:text="@{sparse[index]}"
…
android:text="@{map[key]}"
: 또한 object.key 표기법을 사용하여 맵의 값을 참조할 수도 있다.
android:text="@{map[key]}" // [] 연산자를 사용하여 참조
android:text="@{map.key}" // object.key 표기법을 사용하여 참조
문자열 리터럴
: 작은따옴표를 사용하여 속성 값을 묶어 표현식에 큰따옴표를 사용할 수 있다.
android:text='@{map["firstName"]}'
: 큰따옴표를 사용하여 속성 값을 묶을 수도 있다. 그렇게 했다면 문자열 리터럴을 다시 백 따옴표(`)로 묶어야 한다.
android:text="@{map[`firstName`]}"
리소스
: 앱 리소스를 참조할 수 있다.
android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"
: 매개변수를 제공하여 문자열 형식과 plural를 사용할 수 있다.
android:text="@{@string/nameFormat(firstName, lastName)}"
android:text="@{@plurals/banana(bananaCount)}"
: 속성 및 뷰 참조를 리소스 매개변수로 전달할 수 있다.
android:text="@{@string/example_resource(user.lastName, exampleText.text)}"
: plural가 여러 매개변수를 사용하면 모든 매개변수를 전달해야 한다.
Have an orange
Have %d oranges
android:text="@{@plurals/orange(orangeCount, orangeCount)}"
: 일부 리소스는 표현식 참조를 사용해야 한다.
유형 | 일반 참조 | 표현식 참조 |
String[] | @array | @stringArray |
int[] | @array | @intArray |
TypedArray | @array | @typedArray |
Animator | @animator | @animator |
StateListAnimator | @animator | @stateListAnimator |
color int | @color | @color |
ColorStateList | @color | @colorStateList |
이벤트 처리
- 뷰에서 전달되는 표현식 처리 이벤트를 작성할 수 있다.
- 예: onClick() 메서드
- 이벤트 속성 이름은 몇 가지 예외를 제외하고 리스너 메서드의 이름에 따라 결정된다.
- 예: View.OnClickListener에는 onClick() 메서드가 있으므로 이 이벤트의 속성은 android:onClick).
'기타 > Android' 카테고리의 다른 글
[Android] 안드로이드 Go to the documentation to learn how to Fix dependency resolution errors. 에러 해결 방법 (0) | 2023.04.21 |
---|---|
[Android] Android Activity Lifecycle 정리 (0) | 2023.04.13 |
[Kotlin] This expressions 란? (1) | 2023.02.27 |
[Kotlin] Sealed class 란? (0) | 2023.02.25 |
[Kotlin] Scope functions(let, run, with, apply, also) 정리 (0) | 2023.02.22 |