안드로이드에서 편의를 위해 제공하는 라이브러리의 모음인
jetpack
이 있습니다.
jetpack 은 크게 기초(Foundation), 아키텍처(architecture), 동작(Behavior), 사용자 인터페이스(User Interface) 컴포넌트로 분류됩니다.
저는 이번에 AAC(Android Architecture Component)를 공부해 보고자 합니다. AAC에는 다음과 같은 라이브러리들이 존재합니다.
- Data Binding
- LifeCycles
- LiveData
- Navigation
- Paging
- Room
- ViewModel
- WorkManager
데이터 바인딩이란 명령형 프로그래밍이 아닌 선언적 프로그래밍으로 레이아웃의 UI 구성 요소를 앱의 데이터와 결합하는 라이브러리입니다.
데이터 바인딩을 사용하면 자바 코드를 작성하지 않고 레이아웃 파일에서 직접 프로그래밍 코드를 작성할 수 있습니다. 데이터 바인딩을 함으로써 Boilerplate Code
를 줄여 앱 성능이 향상되고 메모리 누수 및 Null Pointer Exception
을 방지할 수 있습니다.
데이터 바인딩을 설정하려면 프로젝트의 앱 모듈의 build.gradle
에 아래의 코드를 추가합니다.
android {
...
buildFeatures {
dataBinding true
}
}
데이터 바인딩 라이브러리는 레이아웃의 변수와 view 를 참조할 수 있는 Data Binding Class
를 제공합니다.
xml 파일에서 가장 상위 레이아웃을 <layout>
태그로 감싸면 바인딩 클래스가 생성됩니다. 바인딩 클래스의 이름은 기존 xml 파일명을 파스칼 케이스로 변경한 뒤 접미어 Binding
을 붙여 생성됩니다. 예를 들어, activity_main.xml
의 바인딩 클래스 이름은 ActivityMainBinding
입니다.
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
</LinearLayout>
</layout>
데이터 바인딩 클래스를 객체화하여 아래와 같이 바인딩할 수 있습니다.
val binding: ActivityMainBinding =
DataBindingUtil.setContentView(this, R.layout.activity_main)
바인딩 클래스의 이름을 변경하고 싶은 경우 <data>
태그 내 class
속성을 사용하여 변경할 수 있습니다.
<layout>
<data class="Test">
...
</data>
...
</layout>
val binding: Test =
DataBindingUtil.setContentView(this, R.layout.activity_main)
데이터 바인딩을 사용하면 텍스트 뷰의 값을 변경하기 위해 간단히 레이아웃에 변수를 선언하고, 변수에 값을 대입하여 뷰의 상태를 변경할 수 있습니다.
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="myText"
type="String" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
<TextView
android:id="@+id/tv"
...
android:text="@{myText}"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
val binding: ActivityMainBinding =
DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.myText = "Hello World"
<data>
태그 내에 <variable>
태그를 사용하여 선언하면 됩니다. variable 태그는 여러 개 선언가능하며, name과 type 속성을 가집니다. 선언한 변수를 바인딩하려면 @{변수명}
을 사용하면 됩니다.
데이터 클래스도 레이아웃 내에서 변수 선언이 가능합니다. 예를 들어, 아래와 같은 User 라는 데이터 클래스가 있습니다.
data class User (val firstName: String, val lastName: String)
데이터 바인딩을 사용해 데이터 객체의 값을 텍스트뷰에 대입해 보겠습니다.
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="user"
type="com.hhi.tripproject.activity.User" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
<TextView
android:id="@+id/tv"
...
android:text="@{user.firstName}" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
val binding: ActivityMainBinding =
DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.user = User("han", "haein")
다음과 같은 연산자들을 xml 레이아웃에서 사용할 수 있습니다.
산술 연산자 : + - / * %
문자열 연결 : +
논리 연산자 : && ||
비트 연산자 : & | ^
단항 연산자 : + - ! ~
비트 이동 연산자 : >> << >>>
비교 연산자 : == > < >= <=
(<
은 <
로 이스케이핑 해야 합니다.)
Null 병합 연산자 : ??
왼쪽의 피연산자가 null 이라면 오른쪽 피연산자를 선택하도록 하는 연산자입니다.
예를들어, user 객체의 firstName 값이 null 이면 lastName 값을 갖도록 하고 싶다면 아래의 코드와 같이 작성할 수 있습니다.
android:text="@{user.firstName ?? user.lastName}"
<import>
사용<data>
태그에 <import>
태그를 사용하여 참조하고 싶은 클래스를 xml 파일에 불러올 수 있습니다. 예를 들어 View 클래스를 참조하여 View.VISIBLE
과 View.GONE
과 같은 상수를 사용할 수 있습니다.
<data>
<import type="android.view.View"/>
...
<TextView
android:text="@{user.firstName ?? user.lastName}"
android:visibility="@{user.lastName ? View.VISIBLE : View.GONE}"
...
alias 속성을 사용하여 import 하는 클래스의 이름을 변경하여 참조할 수도 있습니다.
<data>
<import type="android.view.View"
alias="VIEW"/>
...
android:text="@{user.firstName ?? user.lastName}"
android:visibility="@{user.lastName ? VIEW.VISIBLE : VIEW.GONE}"