[안드로이드] DataBinding

이상욱·2022년 12월 21일
0

안드로이드

목록 보기
6/17
post-thumbnail
post-custom-banner

✅ DataBinding

데이터 바인딩 라이브러리는 프로그래매틱 방식이 아니라 선언적 형식으로 레이아웃의 UI 구성요소를 앱의 데이터 소스와 결합할 수 있는 지원 라이브러리입니다.기존의 findViewById를 사용할 필요가 없습니다. LiveData를 액티비티에서 따로 observe하는 코드를 작성할 필요가 없습니다.

사용하기

build.gralde(:app)에 dataBinding을 선언해 줍니다.

android {
    ...
        dataBinding {
            enabled = true
        }
}

activity_main.xml

기존 레이아웃을 layout 으로 감싸줍니다. 그리고 내가 사용할 뷰모델을 data 안의 variable에 등록해줍니다.
그리고 뷰모델 안의 변수를 textView에 표시하고 싶을 땐 "@{}" 형식으로 사용해줍니다.

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <data>
        <variable
            name="vm"
            type="com.example.counterapp.MainViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout 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"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{vm.liveCounter.toString()}"
            android:textAppearance="@style/TextAppearance.AppCompat.Large"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/btn_increase"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:text="increase"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/textView" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

MainAcvitivy.kt

메인 액티비티에서는 기존의 setContentView 대신 아래와 같이 DataBindingUtil.setContentView()를 사용해줍니다.
그리고 lifecyclerOwner를 현재 액티비티에 맞춰주고 레이아웃에 data의 variable의 vm에 어떤 뷰모델을 설정할지 작성합니다.

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        val factory = MainViewModelFactory(100, this)

        val mainViewModel by viewModels<MainViewModel> { factory }
        binding.lifecycleOwner = this
        binding.vm = mainViewModel

        binding.btnIncrease.setOnClickListener {
            mainViewModel.increase()
        }


    }
}

✅ BindingAdapter

데이터 바인딩 라이브러리를 사용하면 BindingAdpater를 사용할 수 있습니다. 바인딩 어댑터는 적절한 프레임워크를 호출하여 값을 설정하는 작업을 담당합니다.

build.gradle(:app)파일에 'kotlin-kapt' 플러그인을 추가해줍니다.

plugins {
   ...
    id 'kotlin-kapt'
}

BindingAdpater.kt

원하는 메서드 이름을 지정해주고 View의 확장함수에 함수를 지정합니다. 함수 안에 원하는 로직을 작성합니다.
확장함수를 쓰지않고 매개변수로 View를 전달받아 사용해도 됩니다.

@BindingAdapter("setProgressBar")
fun ProgressBar.setProgress(counter: Int) {
    this.progress = counter

}

두 개 이상의 메서드를 같이 사용하고 싶다면 아래와 같이 사용합니다.

@BindingAdapter(value = ["setProgressBar", "android:max"], requireAll = true)
fun ProgressBar.setProgress(counter: Int, max: Int) {
    this.progress = (counter * 2).coerceAtMost(max)

}

activity_main.xml

해당 뷰에서 bindingAdpater에서 설정한 메서드 이름으로 사용하고 값을 전달합니다.

<ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleHorizontal"
            setProgressBar="@{vm.liveCounter}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:max="@{100}"
            app:layout_constraintBottom_toTopOf="@id/textView"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

✅ 양방향 데이터 바인딩

뷰에서도 뷰모델의 값을 변경할 필요가 있을 때 양방향 데이터 바인딩을 사용합니다.
뷰모델에 값을 하나 선언해줍니다

val hasChecked : MutableLiveData<Boolean> = MutableLiveData(false)

activity_main.xml

xml 파일에서 android:checked부분에서 "@={}" 형태로 사용해주면 양방향 데이터 바인딩이 된다. 이제 뷰에서 checkBox를 클릭하면 뷰모델의 hasChecked도 값이 바뀐다.

<CheckBox
            android:id="@+id/checkBox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="@={vm.hasChecked}"
            android:text="@{vm.hasChecked.toString()}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/btn_increase" />
profile
항상 배우고 성장하는 안드로이드 개발자
post-custom-banner

0개의 댓글