[Android ๊ธฐ์ดˆ] 9. View Binding (๋ทฐ ๋ฐ”์ธ๋”ฉ)
๋ฐ˜์‘ํ˜•

 

 

 

 

kotlin synthetics๋Š” ํ˜„์žฌ deprecated ๋จ

 

 

 

 

1. ๋ทฐ ๋ฐ”์ธ๋”ฉ (View Binding) = ๋ทฐ ๊ฒฐํ•ฉ

  • ๋ทฐ์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋” ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ
  • ๋ทฐ ๋ฐ”์ธ๋”ฉ์„ ์‚ฌ์šฉํ•  ๋•Œ, ์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค๋Š” XML ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์˜ ์ด๋ฆ„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๋ฅผ ์ž๋™ ์ƒ์„ฑ
  • ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๋Š” ๋ ˆ์ด์•„์›ƒ์— ID๊ฐ€ ์žˆ๋Š” ๋ชจ๋“  ๋ทฐ์— ๋Œ€ํ•œ ์ง์ ‘ ์ฐธ์กฐ๋ฅผ ํฌํ•จ, ์ด๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ์—์„œ ์ง์ ‘ ๋ทฐ์— ์ ‘๊ทผ
  • ๋ฐ”์ธ๋”ฉ ๊ฐ์ฒด์˜ ์ด๋ฆ„์€ ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ ์ด๋ฆ„ ๋’ค์— 'Binding'์„ ๋ถ™์—ฌ ๋งŒ๋“ค์–ด์ง
    (์˜ˆ) ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ ์ด๋ฆ„์ด `activity_main.xml`์ธ ๊ฒฝ์šฐ, ์ƒ์„ฑ๋˜๋Š” ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค์˜ ์ด๋ฆ„์€ `ActivityMainBinding`
    (์˜ˆ) ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ ์ด๋ฆ„์ด `fragment_home.xml`์ธ ๊ฒฝ์šฐ, ์ƒ์„ฑ๋˜๋Š” ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค์˜ ์ด๋ฆ„์€ `FragmentHomeBinding`
  • ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๋ทฐ ๋ฐ”์ธ๋”ฉ์ด findViewById๋ฅผ ๋Œ€์ฒด

 

 

 

 

2. findViewById์™€์˜ ์ฐจ์ด์ 

 

1) Null ์•ˆ์ „์„ฑ (Null Safety)

  • ๋ทฐ ๋ฐ”์ธ๋”ฉ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด, ์•ฑ์ด ๋ ˆ์ด์•„์›ƒ์˜ ๊ฐ ๋ทฐ๋ฅผ ์ง์ ‘ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์•ˆ์ „ํ•œ ์ฝ”๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑ
  • ์ด๋Š” ๋ทฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ 'null' ๊ฐ’์œผ๋กœ ์ธํ•œ ์˜ค๋ฅ˜,
    ์ฆ‰ ๋ทฐ๊ฐ€ ์•„์ง ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•˜๋Š”๋ฐ ๊ทธ ๋ทฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋“ค์„ ์˜ˆ๋ฐฉ
  • (์˜ˆ) ๋ ˆ์ด์•„์›ƒ์— ๋ฒ„ํŠผ์ด ์žˆ์–ด์•ผ ํ•˜๋Š”๋ฐ ์•„์ง ๋ฒ„ํŠผ์ด ์ƒ์„ฑ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ
    -> ๋ทฐ ๋ฐ”์ธ๋”ฉ์€ ์ด๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜์—ฌ ์•ฑ์ด ์ถฉ๋Œํ•˜์ง€ ์•Š๋„๋ก ํ•จ
  • (์˜ˆ) ๋ ˆ์ด์•„์›ƒ์˜ ์ผ๋ถ€๋งŒ ๋ทฐ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ
    -> ๋ทฐ ๋ฐ”์ธ๋”ฉ์€ ํ•ด๋‹น ๋ทฐ๊ฐ€ '๊ฐ€๋Šฅ์„ฑ ์žˆ๋Š” null'(Nullable)์ž„์„ ์•Œ๋ ค์ฃผ์–ด, ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ฃผ์˜๋ฅผ ์คŒ

 

2) ํƒ€์ž… ์•ˆ์ „์„ฑ (Type Safety)

  • XML ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์—์„œ ์ •์˜๋œ ๋ทฐ์˜ ํƒ€์ž…๊ณผ ์ž๋™ ์ƒ์„ฑ๋œ ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค์˜ ํ•„๋“œ ํƒ€์ž…์ด ํ•ญ์ƒ ์ผ์น˜ํ•จ
    ๋”ฐ๋ผ์„œ ํƒ€์ž…์ด ์„œ๋กœ ๋งž์ง€ ์•Š์•„ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ฐฉ์ง€
  • (์˜ˆ) ์ด๋ฏธ์ง€ ๋ทฐ(ImageView)์— ํ…์ŠคํŠธ๋ฅผ ์„ค์ •ํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ• ํ…๋ฐ, ๋ทฐ ๋ฐ”์ธ๋”ฉ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋Ÿฐ ์‹ค์ˆ˜๋ฅผ ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์—†์–ด์ง. ์ฆ‰, ์ด๋ฏธ์ง€ ๋ทฐ๋Š” ์ด๋ฏธ์ง€ ๋ทฐ๋กœ, ํ…์ŠคํŠธ ๋ทฐ๋Š” ํ…์ŠคํŠธ ๋ทฐ๋กœ๋งŒ ์‚ฌ์šฉ๋˜๊ฒŒ ํ•˜์—ฌ, ์ž˜๋ชป๋œ ํƒ€์ž… ์‚ฌ์šฉ์œผ๋กœ ์ธํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ๋ณด์žฅ

 

 

 

 

3. ์ฝ”ํ‹€๋ฆฐ์œผ๋กœ ๋ทฐ ๋ฐ”์ธ๋”ฉ ์„ค์ • ๋ฐ ์‚ฌ์šฉ๋ฒ•

 

1) gradle์„ค์ •

(ํ•„์ˆ˜) ๋ชจ๋“ˆ ์ˆ˜์ค€ build.gradle ํŒŒ์ผ

android{
...
    buildFeatures{
     viewBinding = true
    }
}
```
(์„ ํƒ) ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋™์•ˆ ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์„ ๋ฌด์‹œ -> ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์— ์ถ”๊ฐ€

<LinearLayout
        ...
        tools:viewBindingIgnore="true" >
    ...
</LinearLayout>
  • ๋ทฐ ๋ฐ”์ธ๋”ฉ์€ ๋ชจ๋“ˆ๋ณ„๋กœ ์‚ฌ์šฉ ์„ค์ •๋จ
  • ๋ชจ๋“ˆ์—์„œ ๋ทฐ ๋ฐ”์ธ๋”ฉ์„ ์‚ฌ์šฉ ์„ค์ •ํ•˜๋ ค๋ฉด ๋ชจ๋“ˆ ์ˆ˜์ค€ build.gradle ํŒŒ์ผ์—์„œ viewBinding ๋นŒ๋“œ ์˜ต์…˜์„ true๋กœ ์„ค์ •
  • ๋งŒ์•ฝ ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋™์•ˆ ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์„ ๋ฌด์‹œํ•˜๋ ค๋ฉด
    tools:viewBindingIgnore="true" ์†์„ฑ์„ ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์˜ ๋ฃจํŠธ ๋ทฐ์— ์ถ”๊ฐ€

 

 

2) Activity์—์„œ ์„ค์ •

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import com.example.ActivityMainBinding

class MainActivity : AppCompatActivity() {

	private lateinit var binding: ActivityMainBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
    	super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)  
        val view = binding.root    // ์•„๋‹ˆ๋ฉด ์ด๊ฑฐ ์—†์ด ๋ฐ”๋กœ setContentView(binding.root)
        setContentView(view)

}
ํ˜น์€ val by lazy๋กœ ๊ตฌํ˜„

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import com.example.ActivityMainBinding

class MainActivity : AppCompatActivity() {

	private val binding: ActivityMainBinding by lazy {
            binding = ActivityMainBinding.inflate(layoutInflater)  
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
    	super.onCreate(savedInstanceState)
        setContentView(binding.root)

}
  • ํด๋ž˜์Šค๋ฅผ ์œ„์™€ ๊ฐ™์ด ๋งŒ๋“ฆ (๋‘ ๊ฐœ์˜ ์„ฑ๋Šฅ ์ฐจ์ด๋Š” ์—†์Œ)
  • inflate๋Š” xml์— ์žˆ๋Š” ๋ทฐ๋ฅผ ๊ฐ์ฒดํ™”
  • ์›๋ž˜๋Š” R.layout.activity_main์„ ๋„˜๊ฒจ์ฃผ์ง€๋งŒ ์ด๋ฒˆ์—๋Š” ์—ฌ๊ธฐ์„œ ์ƒ์„ฑํ•œ ๋ฃจํŠธ ๋ทฐ๋ฅผ ๋„˜๊ฒจ์คŒ
  • binding๋œ ๊ฐ์ฒด ์•ˆ์— ์žˆ๋Š” id์— ์ ‘๊ทผํ•˜์—ฌ ์‚ฌ์šฉ
    (์˜ˆ) binding.button1.text = "์•ˆ๋…•"
    (์˜ˆ) binding.button2.setBackgroundColor(Color.BLACK)

 

 

 

4. ๋ทฐ ๋ฐ”์ธ๋”ฉ ์˜ˆ์ œ

 

1) ๋นŒ๋“œ ์„ค์ • ์ถ”๊ฐ€

build.gradule (Module :app)

buildFeatures{
     viewBinding = true
    }
}

 

2) Layout XML ์ž‘์„ฑ

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/myTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/myButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/myTextView" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

3) MainActivity.kt ์ž‘์„ฑ

MainActivity.kt

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

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

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.myButton.setOnClickListener{
            binding.myTextView.text = "๋ฐ”์ธ๋”ฉ ์ถœ๋ ฅ"   // ๋ณด๊ณ  ์žˆ๋Š” ํ…์ŠคํŠธ๊ฐ€ ๋ฐ”๋กœ ์ˆ˜์ • ๋จ. ์ง์ ‘ ์ฐธ์กฐ, ์ˆ˜์ • ๊ฐ€๋Šฅ
        }
    }
}

 

 

 

๐Ÿ”จ ์ฐธ๊ณ ํ•˜๊ธฐ ์ข‹์€ ์‚ฌ์ดํŠธ

 

 

๋ทฐ ๊ฒฐํ•ฉ  |  Android ๊ฐœ๋ฐœ์ž  |  Android Developers

์ด ํŽ˜์ด์ง€๋Š” Cloud Translation API๋ฅผ ํ†ตํ•ด ๋ฒˆ์—ญ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•ด ์ •๋ฆฌํ•˜๊ธฐ ๋‚ด ํ™˜๊ฒฝ์„ค์ •์„ ๊ธฐ์ค€์œผ๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ถ„๋ฅ˜ํ•˜์„ธ์š”. ๋ทฐ ๊ฒฐํ•ฉ์€ ๋ทฐ์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋” ์‰ฝ๊ฒŒ ์ž‘์„ฑํ• 

developer.android.com

 

 

 

 

๋ฐ˜์‘ํ˜•
 ๐Ÿ’ฌ C O M M E N T