달나라 노트

Android Studio - ViewBinding 본문

Android

Android Studio - ViewBinding

CosmosProject 2021. 3. 23. 00:07
728x90
반응형

 

 

 

보통 view를 찾기 위해선 findViewById(id)를 이용합니다.

 

그러나 코딩을 하다보면 위 방법이 번거로울 수 있습니다.

 

그럴때는 원하는 view를 좀 더 쉽게 찾게 해주는 view binding을 사용할 수 있죠.

 

이를 위해선 build.gradle 파일을 수정해야합니다.

(build.gradle 파일은 2개가 존재할겁니다. 하나는 project용, 하나는 module용. 이번에는 module용 build.gradle 파일을 수정해야합니다.)

 

plugins {
    ...
}

android {
    ...
    buildFeatures {
        viewBinding = true
    }
    ...
}

dependencies {
    ...
}

build.gradle 파일의 android 부분에 위와같이 buildFeatures를 추가하고, viewBinding을 true로 설정해줍니다.

 

 

그러면 아래 이미지와같은 메세지가 Android Studio 화면의 상단에 뜰겁니다.

Sync Now를 클릭해줍시다.

 

 

 

Sync가 완료되면 MainActivity.kt 파일을 아래처럼 수정해줍시다.

view binding을 활성화시킨다고 이해합시다.

package com.example.diceroller

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.diceroller.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)

        setContentView(binding.root)

        // Write your code
    }
    
    // Write your code
}

 

 

 

 

 

그러면 binding을 어떻게 사용할 수 있는지 알아봅시다.

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/result_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="36sp"
        android:text="This is test text."
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <Button
        android:id="@+id/button_test_change"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:backgroundTint="#676767"
        android:text="Button"
        android:textColor="#8CB3FF"
        app:layout_constraintTop_toBottomOf="@id/result_text"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

 

 

 

MainActivity.kt

package com.example.diceroller

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.diceroller.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)

        setContentView(binding.root)

        var btn = binding.buttonTestChange
        btn.setOnClickListener() {
            text_change()
        }
    }

    fun text_change() {
        binding.resultText.text = "New text"
    }
}

위 내용을 보면 binding 객체를 ActivityMainBinding으로부터 생성해놓고, 마침표를 이용해 여러 view id에 접근하고 있습니다.

 

view id가 정해지는 기준은 activity_main.xml에서 설정한 각 view의 ID가 camel 표기법에 따라 자동으로 변한 것입니다.

이때 알파벳이 아닌 underscore(_)같은 문자는 사라지고 알파벳만 남은채로 camel 표기의 형태로 변하는 것이죠.

 

 

 

 

 

 

 

 

 

 

 

 

package com.example.diceroller

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.diceroller.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)

        setContentView(binding.root)

        // Write your code
    }
    
    // Write your code
}

자 여기서 view binding을 사용할 수 있는 다른 코드를 알아보겠습니다.

위 코드를 보면 lateinit으로 binding 변수를 생성하고 binding 변수의 타입을 ActivityMainBinding을 담았습니다.

나중에 binding 변수에 할당될 값이 ActivityMaingBinding 타입이라는 것이죠.

그리고 onCreate 함수에서 binding을 사용할 때 binding = ActivityMainBinding.inflate(layoutInflater)라는 코드로 binding을 inflate해주고있죠.

 

binding을 사용하려면 반드시 inflate 과정을 거쳐야 하기 때문에 위같은 코드는 함수에서 binding을 사용할 때 마다 inflate 코드를 작성해야 함을 의미합니다.

 

근데 이건 좀 불편하겠죠?

만약 "binding 변수 자체에 나중에 binding 변수를 사용할 때 자동으로 inflate해라" 라는 내용을 넣어서 실제 함수 내에서 binding을 사용할 땐 inflate 코드를 작성하지 않고 사용한다면 훨씬 편해질겁니다.

 

따라서 위 코드를 좀 바꿔보겠습니다.

 

 

package com.example.diceroller

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.diceroller.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    var binding by lazy {
        ActivityMainBinding.inflate(layoutInflater)
    }

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

        setContentView(binding.root)

        // Write your code
        binding.textView.text = "This is test text."
    }
    
    // Write your code
}

위 코드를 보면 binding 변수 선언을 lateinit이 아니라 by lazy를 사용하였습니다.

그리고 by lazy 뒤에 있는 중괄호{} 안에 inflate 구문을 넣어놨죠.

 

by lazy 함수는 변수를 선언할 때 사용되는데

해당 변수를 lateinit처럼 지금 당장 initialize하지는 않지만 나중에 해당 변수를 사용할 때 자동으로 중괄호{} 안에 있는 코드를 사용하여 initialize해라 라는 뜻입니다.

 

즉, var binding by lazy { ... } 라는 뜻은

현재 binding은 값이 아무것도 할당되어있지 않고 변수생성만 되어있다.

다만 추후에 binding 변수를 사용한다면, 중괄호{} 안에 있는 내용을 binding 변수에 할당하여 자동으로 initialize한 후에 사용되게 하라.

 

라는 뜻입니다.

 

그래서 onCreate 함수 내에서 inflate 코드는 전혀 없고 binding.root, binding.textView.text 등 binding을 바로 사용할 수 있음을 볼 수 있죠.

 

 

 

 

728x90
반응형
Comments