Android 앱/Android 개발

11. Data Binding (데이터 바인딩) - Android Studio (안드로이드)

arvigoes 2020. 1. 21. 22:47

데이터 바인딩을 사용하지 않으면 findViewById 같은 함수를 통해 실시간으로 모든 리소스 트리 를 뒤져서 해당 데이터를 찾아가야 합니다. 실시간이라면 실행도중에 발생하는 일이라 프로그램의 수행이 느리게 됩니다.

간단한거 수행하는데 뷰들 찾아다니느라 오래걸린다면 상당히 아깝겠죠?

이런 이유로 데이터 바인딩을 사용 합니다.

미리 바인딩 시켜두고 직접 참조 하게 된다면 일일이 찾아서 할 필요가 없으니 검색 오버해드가 상당히 줄어 들게 됩니다. 모르면 못 쓰지만 알게 되면 무조건 쓰는게 좋을 것 입니다.

대략적인 데이터 바인딩 동작 이미지 입니다.

어떻게 동작하는지 한번 상상해 보세요

 

우선 뷰에대한 데이터 바인딩 먼저 확인 해 보도록 하겠습니다.

데이터 바인딩을 사용하기 우해서는 우선 설정이 필요합니다.

탐색창에서 Grandle Scripts 에서 build.gradle (Module:App) 파일을 열어 보도록 합니다.

build.gradle

Gradle Scripts 에 대해서는

https://arvigoes.tistory.com/85?category=748927

 

4. Android Studio Project 둘러보기(안드로이드)

지난번에 이어서 하려다 내용이 너무 길어져서 Studio 와 Project 로 크게 나눠 보았습니다. 툴에 대해서 어떤내용이 있는지 당장 필요한 내용위주로 알아 봤고 나머지는 천천히 개발하면서 익혀도 충분하니 모르..

arvigoes.tistory.com

에서 간단하게 빌드에 대한  설정및 라이브러리 정보에 대해 포함하고 있다고 알고 넘어갔습니다.

이번에 사용할 데이터 바인딩이 빌드 설정이 필요한 항목이라 여기에 DataBinding 에 대한 정보를 설정 해야 합니다.

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.arvigoes.aboutme"
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    dataBinding {
        enabled = true
    }
}

android 섹션에 dataBinding 에 대한 정보를 추가합니다.

 

layout editor 에서 activity_main.xml 을 layout으로 묶어 둡니다.

아래 코드 참조 바랍니다.

  <!-- 기존코드 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

...................

</LinearLayout>



<!-- 변경코드 -->
<!-- layout 감싸기 -->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

...................

    </LinearLayout>
</layout>

 

기존 MainActivity.kt 파일 내용입니다.

package com.arvigoes.aboutme

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.inputmethod.InputMethodManager
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)

        findViewById<Button>(R.id.done_button).setOnClickListener{
            addNickname(it)
        }
    }

    private fun addNickname(view: View) {
        val editText = findViewById<EditText>(R.id.nickname_edit)
        val nicknameTextView =findViewById<TextView>(R.id.nickname_text)

        nicknameTextView.text = editText.text
        editText.visibility = View.GONE
        view.visibility = View.GONE
        nicknameTextView.visibility = View.VISIBLE

        // Hide the keyboard.
        val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(view.windowToken, 0)
    }
}

변경 해 보도록 하겠습니다.

 

우선 초기화 부터 진행 해 보도록 하겠습니다.

기존에 코드는 주석으로 변경 해 두었습니다.

변경 사항도 체크 하면서 보시길 바랍니다.

package com.arvigoes.aboutme

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.databinding.DataBindingUtil
import com.arvigoes.aboutme.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //setContentView(R.layout.activity_main)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        //findViewById<Button>(R.id.done_button).setOnClickListener{
        //    addNickname(it)
        //}
        binding.doneButton.setOnClickListener {
            addNickname(it)
        }
    }

뷰의 이름은 id 속성의 값으로 카멜표기법을 기준으로 변경됩니다. 

button id : done_button -> doneButton

done_button 클릭 이벤트 등록된 내용도 수정 했습니다.

 

초기화 내용을 바탕으로 addNickname 함수는 직접 한번 수정 해 보세요

제일 끝 부분에 코드는 첨부 해 두도록 하겠습니다.

기존에 사용한 "findViewById" 를 전부 제거 하고 binding 객체를 사용해서 view를 직접 접근 한다고 생각 하시면 됩니다.

 

 

실행 1
실행 2

잘 되네요 

 

 

addNickname 함수 수정 입니다.

    private fun addNickname(view: View) {
        binding.nicknameText.text = binding.nicknameEdit.text
        binding.nicknameEdit.visibility = View.GONE
        view.visibility = View.GONE
        binding.nicknameText.visibility = View.VISIBLE

        // Hide the keyboard.
        val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(view.windowToken, 0)
    }

 

 

 

이번에는 Text등의 Data에 대한 DataBinding 을 알아 보도록 하겠습니다

데이터 바인딩 구성

데이터를 바인딩할 클래스를 먼저 선언해 주도록 합시다.

데이터 클래스를 선언할 파일을 먼저 추가 하도록 합니다.

Kotlin File/Class 선택
file 추가

파일 이름을 MyName 으로 해서 추가를 하도록 합니다.

이름은 마음데로 하셔도 되는데 파일이름 클래스 이름 이런데 이해가 충분하지 않으시다면 우선은 동일하게 하는게 이해하기에 좀 더 도움이 될 것입니다.

MyName.kt 파일

새 파일을 추가하면 추가한 package 정보가 자동으로 포함 됩니다.

이제 MyName data class 를 추가 해 보도록 합시다.

package com.arvigoes.aboutme

data class MyName(var name: String = "", var nickname: String = "")

data class 를 추가 하였으니 data 클래스를 연결 해 보도록 하겠습니다.

activity_main.xml 파일을 text editor 에서 열어서 아래와 같이 추가 합니다.

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- 추가 코드 -->
    <data>
        <variable
            name="myName"
            type="com.arvigoes.aboutme.MyName" />
    </data>
    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/name_text"
        style="@style/NameStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        <!-- 수정 코드 -->
        android:text="@={myName.name}"
        android:textAlignment="center" />
        
 <!-- ................ -->
 
         <TextView
            android:id="@+id/nickname_text"
            style="@style/NameStyle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAlignment="center"
                    <!-- 수정 코드 -->
            android:text="@={myName.nickname}"
            android:visibility="gone" />

여기에서 추가된 <data> 는 MyName 클래스와 view 에 data (myName) 이라는 data 로 바인딩 새켜줍니다.

그리고 <textView 에서 text 로 지정한 android:text = @={myName.name} 으로 변경 해 주도록 합니다.

설명이 좀 어려운데 아래 참조 관계를 보시면 이해가 좀 더 편하리라 생각 됩니다.

DataBinding 참조관계도

이제 MyName 클래스의 값을 초기화 시켜 보도록 하겠습니다.

우선 전체 코드 부터 보고 설명을 하도록 하겠습니다.

package com.arvigoes.aboutme

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.databinding.DataBindingUtil
import com.arvigoes.aboutme.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    // 바인딩할 객체 선언
    private val pmyName: MyName = MyName("Arvigoes")

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

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        // 바인딩 연결 (myName 클래스)
        binding.myName = pmyName
        
        binding.doneButton.setOnClickListener {
            addNickname(it)
        }
    }

    private fun addNickname(view: View) {
        binding.apply {
        	// 바인딩 사용
            myName?.nickname = nicknameEdit.text.toString()
            nicknameEdit.visibility = View.GONE
            doneButton.visibility = View.GONE
            nicknameText.visibility = View.VISIBLE
        }

        // Hide the keyboard.
        val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(view.windowToken, 0)
    }
}

 

kotlin 언어 설명도 포함이 좀 될거 같네요

천천히 보도록 하겠습니다.

private val myName: MyName = MyName("arvigoes")

// MainActivity 클레스의 private 멤버로 myName 이라는 객체를 선언합니다.
// 타입은 MyName 이고 초기값은 "arvigoes" 입니다.
// MyName.kt 파일에 있는 MyName 클래스는 초기값으로 2개를 받고 잇는데
// data class MyName(var name: String = "",var nickname: String = "")
// 초기값은 하나 밖에 없네요?
// var name: String = "" 의 의미는 초기값이 있으면 사용하고 없으면 = ""(빈텍스트) 를 사용한다는 의미 
// 입니다. 이것을 default 값이라고 합니다.
// name 과 nickname 모두 default 값이 있으므로
// MyName 은 MyName() , MyName("이름"), MyName("이름", "닉네임"), MyName(nickname="닉네임") 등
// 모두 사용 가능 합니다.

// 조만간 클래스에 대해서 한번 새로 파서 올려야 겠네요 
// 우선은 참고만 하시면 좋을 것 같습니다.

객체선언

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.myName = pmyName
        // binding 객체에 layout 을 바인딩 합니다.
        // layout 에 포함된 <data>  의 myName 에 private val pmyName: MyName = MyName(name="Arvigoes")
        // 에선언한 myName 객체를 참조 시켜줍니다. 

<data> <variable name="myName" 변수에 객체 참조

    private fun addNickname(view: View) {
        binding.apply {
        // ? 연산자에 대한것도 조만간 포스팅 하도록 하겠습니다.
        // private 멤버 myName 가 아닌 binging.myName 객체의 nickname 에 값을 할당 합니다.
            myName?.nickname = nicknameEdit.text.toString()
        // 변경된 내용의 갱신을 위해 invalidateAll 호출
            invalidateAll()
            nicknameEdit.visibility = View.GONE
            doneButton.visibility = View.GONE
            nicknameText.visibility = View.VISIBLE
        }

참조된 변수 사용

 

실행 해 보도록 하겠습니다.

실행 경과

Data Binding 바인딩은 

view 를 layout 으로 감싸서 kotlin 변수(var binding)에 하는 바인딩

layout 에 변수(<variable name="myName") 를 선언하여 클래스를 바인딩

입니다.

적절하게 잘 사용한다면 실행속도도 많이 향상 시킬수 있고 이점이 많아 보입니다.

data binding 을 활용한 MVVM 패턴도 널리 사용 되고 있으니 바인딩에 대해서는 필히 이해 하시고, 사용방법 또한 어플리케이션이 많이 복잡해서 이해하기 힘들어지기 전에 숙지 하도록 합니다.

view id 가 카멜케이스 로 적용되어 변경되는 점. 등 네이밍 룰에 대해서도 숙지하고 이해 한다면

더 높은 이해도를 가지고 사용 하실 수 있으리라 생각됩니다.

 

아래는 전체 참조 구성도 이니 참고 하시길 바랍니다.