#1 데이터 바인딩 사용 전
#1-1 예시 앱
위과 같은 간단한 앱이 있다. Button을 누르면, EditText의 text가 바로 위에 있는 TextView의 text에 대입된다. 이 앱의 코드는 다음과 같다.
#1-2 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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/my_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="25dp"
android:textSize="30dp"
app:layout_constraintBottom_toTopOf="@id/my_container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/my_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<EditText
android:id="@+id/my_edit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Input any text to print"
android:inputType="text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/my_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Print"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/my_edit_text"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
#1-3 MainActivity.kt
// package com.example.databindingpractice
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myTextView = findViewById<TextView>(R.id.my_text_view)
val myEditText = findViewById<EditText>(R.id.my_edit_text)
val myButton = findViewById<Button>(R.id.my_button)
myButton.setOnClickListener{
myTextView.text = myEditText.text
}
}
}
안드로이드를 처음 배울 때부터 사용했던 findViewById()가 있다. findViewById()는 view(보이는 화면)에 있는 레퍼런스(참조)를 확보하는 방법 중 가장 기초적인 방법이다. findViewById()는 런타임이 아니라 컴파일 시점에 view의 레퍼런스를 확보하기에, 적어도 런타임 중 view에 관한 에러는 나지 않게 보장한다는 장점이 있다. 하지만, TextView와 같은 위젯들의 갯수가 많아지면, 하나하나 findViewById()를 쓰며 뷰 계층에 접근하는 것이 번거로워진다. 동시에 코드의 가독성도 저하된다.
이 때, findViewById()의 장점을 유지하면서, 단점을 해소하는 방법이 있는데 바로 Binding object라는 객체를 사용하는 방법이다. Binding object는 각 layout에 들어있는 모든 view의 레퍼런스를 저장하는 객체다.
#2 데이터 바인딩의 기초적인 사용
#2-1 build.gradle.kts (Module :app)에서 데이터 바인딩 라이브러리 추가하기
plugins {
...
}
android {
...
buildFeatures {
dataBinding = true
}
}
dependencies {
...
}
Binding object를 사용하기위해 먼저, Data Binding 라이브러리(androidx.databinding)를 다운로드해야 한다. 모듈 수준의 그래들 빌드 파일 build.gradle.kts (Module :app)에서 android {...} 안에, buildFeatures { dataBinding = true } 구문을 추가한다. 그래들 버전 4.0미만은 대신 dataBinding { enabled = true } 구문을 추가한다. 이러면 gradle이 알아서 androidx.databinding 라이브러리를 다운로드 한다. 구문을 추가하면 상단에 Sync를 하라는 안내 메시지가 뜨는데, 해당 메시지의 Sync 버튼을 누른다.
#2-2 activity_main.xml에 <layout> 태그 씌우기
<?xml version="1.0" encoding="utf-8"?>
<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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
...
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<?xml version="1.0" encoding="utf-8"?>를 제외한 모든 부분을 <layout> 태그로 감싼다. <layout> 태그는 데이터 바인딩을 위한 레이아웃 파일임을 안드로이드 시스템에 알려준다. 이렇게하면, Data Binding 라이브러리가 자동으로 Binding class를 생성한다. 이제부터 Binding class에서 Binding object를 찍어낼 수 있다. 이 클래스의 이름은 abc_def_ghi.xml라면 AbcDeFGhiBinding으로 정해진다. 즉, _로 구분되는 단어들의 첫글자를 대문자로 바꾼 뒤에 "Binding"이 붙여진다.
xmlns 즉, xml 파일의 네임스페이스 선언(namespace declarations)은 xml 파일에서 가장 외곽(outmost)에 있는 태그의 속성으로 들어가 있어야 한다는 규칙이 있으므로, 원래 있던 자리에서 <layout> 태그로 옮겨준다.
#2-3 MainActivity.kt에서 Binding object 사용하기
// package com.example.databindingpractice
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.example.databindingpractice.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.myButton.setOnClickListener{
binding.myTextView.text = binding.myEditText.text
}
}
}
Activity에서 바인딩 클래스를 사용하는 모습이다. androidx.databinding.DataBindingUtil 클래스의 setContentView()로 초기화를 한다. 원래의 setContentView()는 androidx.appcompat.app.AppCompatActivity의 메소드였다. 하지만, 이름이 같다는 것에서 알 수 있듯 하는 일은 '비슷'할 것임을 유추할 수 있다. binding 객체에는 ActivityMainBinding 클래스의 위젯 id들 즉 activity_main.xml의 위젯 id 정보가 프로퍼티로서 담겨져 있다.
그 프로퍼티의 이름은 Binding 클래스의 이름 규칙과 비슷하게 자동 생성되어있다. xml에서 위젯의 android:id 속성이 "@+id/abc_def_ghi"로 설정되어있다면 abcDefGhi가 프로퍼티명이 된다.
결론적으로, findViewById로 레퍼런스를 하나하나 불러와서 변수 이름을 하나하나 붙이는 방식에 비해 소스 코드 작성 속도가 더 빨라졌으며, 가독성도 좋아졌다.
#2-4 apply 함수 사용
/*
binding.myButton.setOnClickListener{
binding.myTextView.text = binding.myEditText.text
}
*/
binding.apply {
myButton.setOnClickListener {
myTextView.text = myEditText.text
}
}
코틀린의 scope 함수들 중 하나인 apply를 활용하면 위과 같이 코드를 더욱 간소화시킬 수 있다.
#3 요약
Data Binding으로 findViewById()를 일괄 설정할 수 있다.
#4 완성된 앱
'깨알 개념 > Android' 카테고리의 다른 글
[Android] LiveData - 기초 (0) | 2024.01.16 |
---|---|
[Android] ViewModel - 뷰 모델에 인자(Argument) 전달 (ViewModelFactory) (0) | 2024.01.15 |
[Android] ViewModel - 기초 (0) | 2024.01.13 |
[Android] Data Binding - View에 객체 전달 (0) | 2024.01.12 |
AndroidX (구 Support Library) (0) | 2023.12.13 |