데이터 바인딩은 UI를 구성함에 있어 코드상에 반복적인 귀찮은 작업을 해소시켜주는 기능으로 보면 된다.
선언부에 기계적으로 작성해야한 했던 findById() 를 적어도 java파일 안에서 그만 볼수 있으니까
findViewById<TextView>(R.id.sample_text).apply {
text = viewModel.userName
}
이런 코드를 layuot을 구성하는 xml파일 안에서 java파일에서 지정해준 해당 위젯의 변수명과 매치시켜주면 된다.
<TextView
android:text="@{viewmodel.userName}" />
이점은 ?
파일의 단순화, 유지보수의 편리성, 메모리누수 및 nullpoint excention을 방지할수 있다.
1. 빌드환경 - 데이터 바인딩 추가
android {
...
dataBinding {
enabled = true
}
}
dataBinding요소를 build.gradle 에 위와같이 추가해준다.
데이터 결합 라이브러리는 유연성과 광범위한 호환성을 모두 제공하는 지원 라이브러리이며 Android 4.0(API 수준 14) 이상을 실행하는 기기에서 사용할 수 있고, 최신 Gradle용 Android 플러그인을 프로젝트에 사용하는 것이 좋다. 그러나 데이터 결합은 버전 1.5.0 이상에서 지원됨.
2. 레이아웃 및 바인딩 수식
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.User"/>
</data>
</layout>
예를 들어, 위와 같다고 한다면 data태그내의 user라는 변수는 com.example.User의 파일안에서 사용할 수있다.
데이터 결합 - 각 레이아웃 파일의 결합 클래스가 생성됨 (기본적으로 생성 클래스 이름은 레이아웃 파일이름 기반으로 파스칼 표기법으로 변환, 접미사(Binding이 추가됨)
activity_main.xml 레이아웃의 생성되는 클래스는 ActivityMain+Binding = ActivityMainBinding 이 됨
Fragment, ListView 또는 RecyclerView 어댑터 내에서 데이터 결합 항목을 사용하고 있다면 다음 코드 예에서와 같이 결합 클래스 또는 DataBindingUtil 클래스의 inflate() 메서드를 사용할 수도 있다
val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false)
// or
val listItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false)
표현식 언어
산술 + - / * %
문자열 연결 +
논리 && ||
바이너리 & | ^
단항 + - ! ~
전환 >> >>> <<
비교 == > < >= <=(<는 <으로 이스케이프 처리해야 함)
instanceof
그룹화 ()
리터럴 - 문자, 문자열, 숫자, null
변환
메서드 호출
필드 액세스
배열 액세스 []
삼항 연산자 ?:
Null병합 연산자 - null 병합 연산자(??)는 왼쪽 피연산자가 null이 아니면 왼쪽 피연산자를 선택하고 null이면 오른쪽 피연산자를 선택
android:text="@{user.displayName ?? user.lastName}"
//기능적으로 동일
android:text="@{user.displayName != null ? user.displayName : user.lastName}"
* 생성된 데이터 결합 코드는 자동으로 null 값을 확인하고 null 포인터 예외를 방지
. 예를 들어 @{user.name} 표현식에서 user가 null이면 user.name에 null이 기본값으로 할당. age의 유형이 int인 user.age를 참조하면 데이터 결합은 0의 기본값을 사용.
속성 참조 - 표현식은 다음 형식을 사용하여 클래스의 속성을 참조
android:text="@{user.lastName}"
표현식은 다음 구문을 사용하여 ID로 레이아웃의 다른 뷰를 참조할 수 있다
<EditText
android:id="@+id/example_text"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
<TextView
android:id="@+id/example_output"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{exampleText.text}"/> // TextView 뷰는 동일한 레이아웃의 EditText 뷰를 참조
리소스 참조
표현식은 앱 리소스를 참조할 수 있다.
android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"
매개변수를 제공하여 형식 문자열과 복수형을 평가 할수도 있고
android:text="@{@string/nameFormat(firstName, lastName)}"
android:text="@{@plurals/banana(bananaCount)}"
속성 참조 및 뷰 참조를 리소스 매개변수로 전달할 수 있다
android:text="@{@string/example_resource(user.lastName, exampleText.text)}"
// EditText(exampleText.text)에 입력된 텍스트가 user.lastName로 전달되는것 !
이벤트 처리
데이터 결합을 사용하면 뷰에서 전달되는 표현식 처리 이벤트를 작성할 수 있음. 이벤트 속성 이름은 몇 가지 예외를 제외하고 리스너 메서드의 이름에 따라 결정된다. View.OnClickListener에는 onClick() 메서드가 있으므로 이 이벤트의 속성은 android:onClick.
- 메서드 참조: 표현식에서 리스너 메서드의 서명과 일치하는 메서드를 참조. 표현식이 메서드 참조로 계산되면 데이터 결합은 리스너에서 메서드 참조 및 소유자 객체를 래핑하고 타겟 뷰에서 이 리스너를 설정. 표현식이 null로 계산되면 데이터 결합은 리스너를 생성하지 않고 대신 null 리스너를 설정.
class MyHandlers {
fun onClickFriend(view: View) { ... }
}
....
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"
android:onClick="@{handlers::onClickFriend}"/>
...
- 리스너 결합: 이벤트가 발생할 때 계산되는 람다 표현식 데이터 결합은 항상 리스너를 생성하여 뷰에서 설정합니다. 이벤트가 전달되면 리스너는 람다 표현식을 계산
class Presenter {
fun onSaveClick(task: Task){}
}
...
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
<Button android:layout_width="wrap_content" android:layout_height="wrap_content"
android:onClick="@{() -> presenter.onSaveClick(task)}" />
</LinearLayout>
...
메서드 참조와 리스너 결합의 주요 차이점은 실제 리스너 구현이 이벤트가 트리거될 때가 아니라 데이터가 결합될 때 생성된다는 점. 이벤트가 발생할 때 표현식을 계산하려면 리스너 결합을 사용
샘플소스
github.com/android/databinding-samples
참조
developer.android.com/topic/libraries/data-binding/expressions?hl=ko
'Android' 카테고리의 다른 글
[Android]안드로이드 애플리케이션 설계패턴 (0) | 2021.03.28 |
---|---|
아키텍처_애플리케이션의 설계 원칙 (0) | 2021.03.21 |
[Android] Annotation 사용법 및 종류 (0) | 2021.01.09 |
Android 기본 Intent를 사용한 음악 재생 (0) | 2019.04.02 |
GCM->FCM Migration (0) | 2019.04.02 |