📱 안드로이드 Android ~ Kotlin

[Android/Kotiln] 데이터 바인딩 dataBinding 사용하기

핑크빛연어 2021. 9. 2. 16:40

 

dataBinding

 

앱의 데이터 소스와 레이아웃의 구성요소를 결합할 수 있게 해주는 Android JetPack 라이브러리 

findViewById를 쓰지 않고, 데이터 소스와 레이아웃을 결합해주는 방식 

https://developer.android.com/topic/libraries/data-binding/start?hl=ko 

 

시작하기  |  Android 개발자  |  Android Developers

시작하기 Android 스튜디오의 데이터 결합 코드 지원을 비롯하여 개발 환경에서 데이터 결합 라이브러리를 함께 사용하도록 준비하는 방법을 자세히 알아봅니다. 데이터 결합 라이브러리는 유연

developer.android.com

 

 

🚨 장점

 

1. findViewById()를 사용하지 않아도 된다. 자동으로 xml에서 만든 View들을 만들어준다.
2. data 가 바뀌면 자동으로 View 를 변경해준다.
3. 코드의 가독성 이 좋아진다.

 

 

🚨 사용 방법 , 예제 코드

 

build.gradle(:app)

dataBinding 의 enabled 를 true 로 설정합니다. 

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

 

xml 레이아웃 - activity_main.xml

데이터 바인딩을 사용하기 위해 레이아웃 파일 전체를 <layout> 태그로 감쌉니다.
그 안에 <data> 태그 안의 <variable> 태그로 변수를 선언합니다.
variable 태그는 데이터 소스와 연결해주기 위한 태그입니다.
저는 액티비티UserModel  데이터 클래스를 사용하기 위해 variable 태그에 선언하였습니다.

액티비티 데이터 소스의 변수를 사용하려면
"@{activity.nm_date}" 와 같은 방식으로 사용합니다.

액티비티 데이터 소스의 메소드를 사용하려면 
android:onClick="@{() -> activity.onClickGoWeather()}" 와 같은 방식으로 사용합니다.

android:visibility="@{activity.isClickedBtnText == true ? View.GONE : View.VISIBLE}" 처럼 
액티비티 데이터 소스의 변수값에 따라 값을 다르게 표시할 수 도 있습니다.

저는 View 도 사용하기 위해 <data> 안에 View 를 import 하는 소스도 추가하였습니다.

<?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">

    <data>
        <import type="android.view.View" />
        <variable
            name="activity"
            type="com.eun.myweatherkotlin_mvvm_01.view.MainActivity" />
        <variable
            name="user"
            type="com.eun.myweatherkotlin_mvvm_01.data.model.UserModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        tools:context=".view.MainActivity" >

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:background="@color/amber_200"
            android:elevation="10dp"
            android:gravity="center"
            android:text="메인화면"
            android:textColor="@color/black"
            android:textSize="20sp"
            android:textStyle="bold"
            app:layout_constraintBottom_toTopOf="@+id/ll_date"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <LinearLayout
            android:id="@+id/ll_date"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_marginTop="50dp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:layout_marginBottom="20dp"
            android:weightSum="100"
            android:orientation="horizontal"
            android:background="@drawable/bg_custom_title_name"
            android:gravity="center"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tv_title" >
            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="30"
                android:layout_marginRight="2dp"
                android:gravity="right|center_vertical"
                android:text="@{activity.nm_date}"
                android:textStyle="bold"
                android:textColor="@color/white"
                android:textSize="20dp" />
            <TextView
                android:id="@+id/tv_date"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="70"
                android:layout_marginRight="2dp"
                android:gravity="left|center_vertical"
                android:text="@{user.date}"
                android:textColor="@color/white"
                android:textSize="20dp" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/ll_name"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_marginTop="50dp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:layout_marginBottom="20dp"
            android:weightSum="100"
            android:orientation="horizontal"
            android:background="@drawable/bg_custom_title_name"
            android:gravity="center"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/ll_date" >
            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="30"
                android:layout_marginRight="2dp"
                android:gravity="right|center_vertical"
                android:text="@{activity.nm_name}"
                android:textStyle="bold"
                android:textColor="@color/white"
                android:textSize="20dp" />
            <TextView
                android:id="@+id/tv_name"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="70"
                android:layout_marginRight="2dp"
                android:gravity="left|center_vertical"
                android:text="@{user.name}"
                android:textColor="@color/white"
                android:textSize="20dp" />
        </LinearLayout>

        <Button
            android:id="@+id/btn_goWeather"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            android:paddingLeft="30dp"
            android:paddingRight="30dp"
            android:text="Go Weather"
            android:onClick="@{() -> activity.onClickGoWeather()}"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/ll_name" />

        <Button
            android:id="@+id/btn_showToast"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:paddingLeft="30dp"
            android:paddingRight="30dp"
            android:text="Show Toast"
            android:onClick="@{() -> activity.onClickShowToast(user.date+'/'+user.name)}"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/btn_goWeather" />

        <Button
            android:id="@+id/btn_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:paddingLeft="30dp"
            android:paddingRight="30dp"
            android:text="@{activity.isClickedBtnText == true ? activity.btnTextShow : activity.btnTextHide}"
            android:onClick="@{() -> activity.onClickBtnText()}"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/tv_text"
            app:layout_constraintTop_toBottomOf="@+id/btn_showToast" />

        <TextView
            android:id="@+id/tv_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:paddingLeft="10dp"
            android:layout_gravity="center_vertical"
            android:text="@{activity.nm_text}"
            android:visibility="@{activity.isClickedBtnText == true ? View.GONE : View.VISIBLE}"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/btn_text"
            app:layout_constraintTop_toBottomOf="@+id/btn_showToast" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

 

UserModel.kt

data 객체를 view 와 바인딩하기 위해 UserModel 이라는 이름의 data class 를 만듭니다.

package com.eun.myweatherkotlin_mvvm_01.data.model

data class UserModel(
    var date: String,
    var name: String
)

 

MainActivity.kt 

레이아웃과 결합할 수 있게 DataBindingUtil.setContentView() 을 사용해서 
데이터 소스와 레이아웃의 구성요소를 결합시켜 줍니다. 

binding.activity 는 레이아웃의 activity 를 this@MainActivity 로 선언하고
binding.user 는 레이아웃의 user 를 UserModel 클래스의 객체로 결합하여 set 해주는 것을 의미합니다.

액티비티 Activity vs 프래그먼트 Fragment 의 사용방식 입니다.

//Activity 
val binding = DataBindingUtil.setContentView(this, R.layout.activity_main) 

//Fragment 
val binding = DataBindingUtil.inflate(inflater, R.layout.activity_main, container, false)

package com.eun.myweatherkotlin_mvvm_01.view

import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.eun.myweatherkotlin_mvvm_01.R
import com.eun.myweatherkotlin_mvvm_01.data.model.UserModel
import com.eun.myweatherkotlin_mvvm_01.databinding.ActivityMainBinding
import com.eun.myweatherkotlin_mvvm_01.util.stringTime

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding  //activity_main.xml 을 바인딩

    var nm_date = "날짜 : "
    var nm_name = "이름 : "
    var nm_text = MainActivity::class.java.simpleName

    var isClickedBtnText = false
    var btnTextHide = "HIDE"
    var btnTextShow = "SHOW"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)  //DataBindingUtil 을 통해 view layout 초기화
        binding.activity = this@MainActivity  //binding 객체의 activity 를 MainActivity 로 설정
        binding.user = UserModel(stringTime, "홍길동")  //UserModel 객체를 초기화하여 binding 객체의 user 에 set 해준다
    }

    /* WeatherActivity 로 이동 */
    fun onClickGoWeather() {
        val intent = Intent(this, WeatherActivity::class.java)
        startActivity(intent)
    }

    /* Toast 띄우기 */
    fun onClickShowToast(text: String) {
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
    }

    /* isClickedBtnText 에 따라 TEXT 표시 여부 변경하기 */
    fun onClickBtnText() {
        isClickedBtnText = !isClickedBtnText
        binding.invalidateAll()  //UI 새로고침 하기 위해서 새로운 리바인드를 요청
    }

}

 

CommonUtil.kt

CommonUtil 은 현재시간을 사용하기 위해 만든 공통 파일입니다.

package com.eun.myweatherkotlin_mvvm_01.util

import java.text.SimpleDateFormat
import java.util.*

// 현재시간을 가져오기
val now: Long = System.currentTimeMillis()

// 현재 시간을 Date 타입으로 변환
val date = Date(now)

// 날짜, 시간을 가져오고 싶은 형태 선언
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale("ko", "KR"))

// 현재 시간을 dateFormat 에 선언한 형태의 String 으로 변환
val stringTime = dateFormat.format(date)

// String 형태의 시간을 Long 형으로 변환
val longTime = dateFormat.parse(stringTime).time

//String 형태의 시간을 Date 형으로 변환
val dateTime = dateFormat.parse(stringTime)

 

 

결과 화면

 

 

 

감사합니당!

728x90
반응형