Jetpack 컴포넌트는 생산성을 높인 개발을 도우는 라이브러리로, 아래와 같은 특징이 있습니다
1. 애플리케이션 설계 권장사항을 따름
2. 보일러 플레이트 코드 줄임
3. 복잡한 작업들 간소 -> 중요 코드에만 집중
Jetpack 컴포넌트는 Foundation, Architecture, Behavior, User Interface 4개의 카테고리를 가지는데 그 중 Architecture에 대해서 알아보겠습니다
DataBinding
xml을 앱의 데이터와 결합할 수 있는 라이브러리
- findViewById 메소드를 호출할 필요가 없어 앱 성능이 향상, 메모리 누수 및 NPE를 방지할 수 있다
💬 호출할 필요가 없는 이유 ?
바인딩 클래스 내부에서 미리 findViewById를 호출하고 그 결과를 캐싱해두기 때문에
- View를 선언하고 데이터를 넣어주는 코드가 사라져서 보일러 많은 플레이트 코드가 줄어듭니다
🔍 DataBinding 설정하기
설정하기 전 아래의 버전 이상이 필요합니다
Android 4.0이상
Android Studio 1.5.0 이상
build.gradle(app)
dataBinding {
enabled = true
}
위와 같이 build.gradle에 선언합니다
이제 Databinding을 사용할 준비는 끝났습니다🏁
🔍 Binding 클래스 생성하기
xml에서 직접 데이터와 결합시키는 형태이다보니, 기존의 xml 파일과는 생김새가 조금 달라집니다
레이아웃의 변수와 뷰를 참조할 수 있는 Binding 클래스를 생성해보겠습니다
xml 파일에서 가장 상위 레이아웃을 <layout>으로 감싸주면 자동으로 바인딩 클래스가 생성됩니다
이 때 클래스의 명은 xml파일명을 파스칼케이스로 변경 후 Binding이 붙은 형태가 됩니다
ex) activity_main.xml ▶️ ActivityMainBinding
<layout>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
orientation:="vertical"/>
</layout>
🔍 Binding 객체 생성
Binding 객체 생성에는 여러가지 방법이 있습니다
1. inflate()
- 레이아웃 전개와 함께 객체를 선언
// in Activity
val biding = ActivityMainBinding.inflate(layoutInflater)
// in Fragment
val binding = ActivityMainBinding.inflate(LayoutInflater.from(context), this, false)
2. bind()
- 레이아웃이 전개된 후 바인딩할 경우 사용
val binding = ActivityMainBinding.bind(rootView)
3. DataBinding.Util
- 바인딩 클래스의 이름을 미리 알지 못하는 경우 사용
//use inflate
val binding = DataBindingUtil.inflate(
layoutInflater,
R.layout.activity_main,
parent,
attachToParent
)
//use bind
val binding = DataBindingUtil.bind(rootView)
- DataBindingUtil내엔 setContentView 메서드가 포함되어 있어 activity의 setContentView를 대체할 수도 있습니다
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
🔍 xml에 변수 선언하기
위에 말했던 것과 같이 DataBinding은 레이아웃 id를 선언하고 뷰에 접근할 필요 없이
xml에서 변수를 선언하고 변수에 값을 대입하는 것으로 뷰의 상태를 변화시킬 수 있습니다
이를 위해 xml에서 변수를 어떻게 선언하는지 알아보겠습니다
변수선언은 <layout>태그 내의 <data>를 사용해야합니다
<data>내에서 <variable>을 사용해 선언하고 싶은 변수를 선언합니다
<variable>은 여러 개 선언이 가능하고 name(변수 이름), type(변수의 자료형) 속성을 가집니다
<layout>
<data>
<variable
name="tvTest"
type="String"/>
</data>
</layout>
위와 같이 선언한 변수를 바인딩하려면 @{변수명} 을 사용합니다
<Textview
android:id="@id/tvShow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{tvTest}" />
📌 만약, xml에서 아닌 binding 클래스에서 변수에 값을 대입하려면 setter메서드를 사용합니다
xml에서 선언한 변수명에 set이 접두어로 붙은 메서드가 생성되어있습니다
binding.setTvTest("Hello World")
또, 변수엔 원시형태가 아닌 POJO클래스도 선언이 가능합니다
<layout>
<data>
<variable
name="person"
type="POJO 클래스의 위치"/>
</data>
</layout>
person 클래스에 getName 메서드가 있다고 가정했을 때,
<Textview
android:id="@id/tvShow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{person.getName}" />
View에 데이터를 할당하는 방식은 똑같고, variable 선언 시 type이 클래스의 위치가 들어간다는 차이점이 있습니다
🔍 Binding 표현식
보다 유연한 사용을 위해 바인딩의 표현식에 간단히 알아보겠습니다
바인딩은 지원하는 문법이 많으므로, 어떤 문법들을 지원하느지에 대해선 자세히 다루진 않겠습니다
아래와 같이 연산자의 사용도 자유롭습니다
android:visibility="@{num > 28 ? View.GONE:View.VISIBLE}"
android:text="@{person.getName ?? "empty"}
Collections 클래스들도 사용이 가능합니다
⚠️ 주의할 점은 <는 <로 이스케이핑이 필요합니다
<import>는 참조하고싶은 클래스를 xml에 가져옵니다
만약, 클래스의 이름이 동일하다면 <import>내에 alias메서드를 사용해 alias ="변경할 이름" 로 이름을 변경할 수 있습니다
<data>
<import type="android.util.SparseArray"/>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/>
<variable name="sparse" type="SparseArray<String>"/>
</data>
<Textview
android:id="@id/tvShow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{list[index]}" />
<Textview
android:id="@id/tvShow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{sparse[index]}" />
🔍 Binding 이벤트
1. 메서드 참조
Handler를 사용해 직접 바인딩, 메서드명과 매개변수가 반드시 일치해야함
class ListenerHandler {
fun onClickTv(v : View) { }
}
<data>
<variable name="listener" type="핸들러 클래스 위치"/>
</data>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@id/tvTest"
android:onClick="@{listener.onClickTv}" />
2. Listener Binding
- 반환 타입만 일치시켜도 가능
class Change {
fun onChanged(task: Task, done: Boolean){}
}
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onCheckedChanged="@{(cb, isChecked) ->
change.onChanged(task, isChecked)?" />
여기까지 기본적인 사용법을 알아보았습니다
다음은 좀 더 심화된 사용법을 알아보겠습니다
'📱 Android' 카테고리의 다른 글
[Android] Activity LifeCycle 🧐 (0) | 2022.07.03 |
---|---|
[Android] MVVM 구현하기 (0) | 2022.06.27 |
[Android] Pattern (MVC, MVP, MVVM) (0) | 2022.05.30 |
[Android] Clean Architecture in Android (0) | 2022.05.29 |
[Firebase SDK 추가 이슈] build.gradle in Bumblebee (0) | 2022.05.22 |