오늘은 ACC의 하나인 Databinding에 대하여 공부해봅시다. Databinding은 안드로이드 앱에서 MVVM Architecture을 구현하기 위해 주로 사용합니다. 보통 ViewModel과 LiveData와 같이 사용합니다.
1️⃣ DataBinding이란?
기존의 View를 참조하기 위해서 보통 findViewById
를 사용하였다. findViewById
는 런타임에 view계층을 탐색하여 찾습니다. View가 깊어질수록 탐색 시간이 더 길어지므로 사용자 입장에서 앱을 사용할 때 반응을 느리게 할 수 있는 요소가 됩니다.
하지만 Databinding
을 사용하면 컴파일 타임에 activity나 Fragment와 layout을 연결할 수 있습니다. 컴파일러는 activity가 생성될 때 binding class라고 불리는 helper class와 binding class의 인스턴스를 생성합니다. 이를 통해 쉽게 View에 접근할 수 있습니다.
DataBinding : View와 UI Component(Activity or Fragment)를 연결해주기 위한 AAC
2️⃣ DataBinding을 사용하는 이유
DataBinding은 다음과 같은 이유로 사용합니다.
1) 데이터를 UI 요소에 연결하기 위해 필요한 코드를 최소화할 수 있다.
2) layout에서의 표현식 혹은 변수 제공하지 하므로 동적인 UI를 만들 수 있다.
3) xml에서 로직을 바로 연결하기 때문에 View와 ViewModel의 역할을 확실하게 분리할 수 있다. (MVVM 패턴을 구현하기 용이)
4) xml resouce만 보고도 view에 어떤 데이터가 사용되는지 파악이 가능하다.
5) 각 View에 attribute를 Custom 할 수 있다.
6) 양방향 데이터 결합을 사용할 수 있다. (ViewBinding과 차이점)
7) 메모리 누수 및 null 포인터 예외 방지
8) 앱 퍼포먼스 향상
3️⃣ DataBinding 사용 하기
우선 build.gradle
파일의 android 안에 databinding 속성을 추가해줍니다.
android {
...
dataBinding {
enabled true
}
}
View에 <layout> 태그를 추가해줍니다. 쉽게 추가하는 방법은 최상단 View에서 오른쪽 클릭 후 Show Context Actions → Convert to data binding layout 클릭하면 자동으로 변경해줍니다. <data> 태그는 layout variables를 담을 수 있습니다. name은 xml안에서 사용할 변수 이름이고 type은 해당 layout variable의 타입을 의미합니다.
<layout 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">
<data>
<variable
name="viewmodel"
type="com.example.android.databinding.basicsample.data.SimpleViewModel"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
...
layout variables는 layout expressions를 통해 사용할 수 있습니다. 방식은 @{expression}입니다.
// 변수 binding
android:text="@{viewmodel.name}"
// 변수 binding
android:visibility="@{viewmodel.nameVisible}"
// 메서드 binding
android:onClick="@{() -> viewmodel.onLike()}"
이제 View에서 모든 variable를 정의했다면 Activity나 Fragment에서 다음과 같이 연결해주어야 합니다. 그리고 <data> 태그에서 정의한 layout variables를 결합해야 합니다. 또한 동적인 UI를 위해 생명주기를 결합해야 합니다.
class MainActivity : AppCompatActivity() {
private val viewModel by lazy { ViewModelProviders.of(this).get(SimpleViewModel::class.java) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding : MainActivityBinding =
DataBindingUtil.setContentView(this, R.layout.main_activity)
binding.lifecycleOwner = this //UI를 동적으로 변경 시키기 위해 생명주기를 관찰할 수 있게 설정
binding.viewmodel = viewModel //layout variable에서 정의한 viemodel 연결
}
}
4️⃣ Two-way Binding 방법
//단방향
<CheckBox
android:id="@+id/rememberMeCheckBox"
android:checked="@{viewmodel.rememberMe}"
android:onCheckedChanged="@{viewmodel.rememberMeChanged}"
/>
//양방향
<CheckBox
android:id="@+id/rememberMeCheckBox"
android:checked="@={viewmodel.rememberMe}"
/>
Databinding에서는 양방향 데이터 결합을 제공합니다. 이는 "@={}"로 지정할 수 있습니다. 예를 들어서 다음과 코드가 있다고 하면 다음과 같이 동작할 수 있습니다.
//in viewmodel
val name : MutableLiveData<String> = MutableLiveData()
<EditText
android:id="@+id/name"
android:text="@={viewmodel.name}"
... />
이제 EditText에 입력을 하면 해당 내용이 viewmodel에 반영이 됩니다. 반대로도 마찬가지로 결합이 됩니다.
5️⃣ @BindingAdapter
@BindingAdapter
를 통해 View에 새로운 attribute를 지정할 수 있습니다. 그리고 이를 적용하기 위해서는 Object class안에 정의하거나 일반 kotlin파일에 정의해야 합니다.
@BindingAdapter("app:hideIfZero")
fun hideIfZero(view: View, number: Int) {
view.visibility = if (number == 0) View.GONE else View.VISIBLE
}
이렇게 정의한 BindingAdapter는 다음과 같이 사용할 수 있습니다.
<ProgressBar
android:id="@+id/progressBar"
app:hideIfZero="@{viewmodel.likes}"
...
이를 통해서 View와 비즈니스 로직을 분리하기 쉬워집니다.
6️⃣ 참고하기 좋은 글
추가적으로 ViewModel이나 LiveData에 대해 공부하고 싶으시면 아래의 글을 참고해주세요.
2022.04.16 - [개발/Android] - [Android] ACC ViewModel이란? - 정의, 사용법, 주의할 점
2022.05.10 - [개발/Android] - [Android] LiveData에 대해 알아보자
'개발 > Android' 카테고리의 다른 글
[Android] 두 개의 RecyclerView 사이에서 Drag and Drop 구현하기 (2) | 2022.09.17 |
---|---|
[Android] 런처앱(Launcher app)에서 Widget 생성하기 (0) | 2022.09.01 |
[Android] The emulator process for AVD has terminated 오류 해결 (0) | 2022.07.09 |
[Android] 백그라운드 작업을 위한 Service (1) - 기본 개념 (0) | 2022.07.05 |
[Android] 리스트 업데이트를 위한 ListAdapter (0) | 2022.06.07 |
댓글