#1 ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ
#1-1 ๋จ๋ฐฉํฅ๊ณผ ์๋ฐฉํฅ
์ง๊ธ๊น์ง ํด์จ Data Binding์ ๋จ๋ฐฉํฅ(One Way) ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ด์๋ค. Model ๋๋ ViewModel์์ View๋ก ๊ฐ๋ ํ๋ฆ์ผ๋ก๋ง ๋ฐ์ดํฐ๊ฐ ๊ฐฑ์ ๋๋ค. ์ญ์ ์ฑ๋ฆฝํ์ง ์๋๋ค. ์ญ์ด ์ฑ๋ฆฝํ์ง ์๋ ๊ฒ ๊ผญ ๋์ ๊ฒ๋ ์๋๋ค. ๋ง์น ์ธํฐ๋ท ์ผํ๋ชฐ์์ ์ด๋ค ๋ฌผ๊ฑด์ ํ์๋ ๊ฐ๊ฒฉ์, ๋ธ๋ผ์ฐ์ ์ ๊ฐ๋ฐ์ ๋ชจ๋๋ฅผ ํตํด ๋ณ๊ฒฝํ๋ค๊ณ ์๋ฒ์ ์ ์ฅ๋ ์ค์ ๊ฐ๊ฒฉ์ด ๋ณํ์ง ์๋ ๊ฒ๊ณผ ๊ฐ๋ค. ๋ง์ ํ๋ ๋ณํ๋ ์ผ๋ ์์ด์ผํ๊ณ ๋ง์ด๋ค.
#1-2 ์์ ํ ์ํ ์ฑ
[Android] LiveData - ์์์ ์ผ๋ก '๊ด์ฐฐ'ํ๊ธฐ
#1 ViewModel ์์ LiveData๊ฐ ์๋ ์ํ ์ฑ [Android] ViewModel - View์ ๊ฐ์ฒด(ViewModel) ์ ๋ฌ #1 ๊ฐ์ #1-1 Data Binding๊ณผ ViewModel [Android] Data Binding - View์ ๊ฐ์ฒด ์ ๋ฌ #1 ๊ฐ์ฒด ์ ๋ฌ์ ํ์์ฑ #1-1 ์ด์ ๊ธ Data Binding -
kenel.tistory.com
์ ๊ฒ์๊ธ์ ์์ฑ๋ ์ฑ์ ์์ ํด์, ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ์๋์ ํ์ธํด๋ณธ๋ค.
#1-3 activity_main.xml ์์
<?xml version="1.0" encoding="utf-8"?>
<layout ...>
...
<androidx.constraintlayout.widget.ConstraintLayout ...>
...
<EditText ... />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<TextView>๋ฅผ <EditText>๋ก ๋ฐ๊พผ๋ค
#1-4 ์๋ ํ์ธ - ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ

<Button>์ 7๋ฒ ํด๋ฆญํ๋ค. ์ด๋ฌ๋ฉด, ViewModel์ ํ๋กํผํฐ count์ ๋ํด, MainActivityViewModel.updateCount(){ count++ }๊ฐ 7๋ฒ ์ํ๋๋ค. ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ์ํด <EditText>์๋ 7์ด ๋ด๊ธด๋ค.
์ด๋ฒ์ ์ฌ์ฉ์(๋)๊ฐ ์ง์ <EditText>๋ฅผ ์กฐ์ํ๋ค. 7์ 3์ผ๋ก ๋ฐ๊พผ๋ค. ์ด ๋, ๋ด๋ถ์ ์ธ count์ ๊ฐ์ ์ฌ์ ํ 7์ด๋ค. ์ฌ์ฉ์๊ฐ ์ง์ <EditText>๋ฅผ ์กฐ์ํ๋ค๊ณ , ViewModel์ ํ๋กํผํฐ์ ์ด๋ค ์ํฅ์ ๋ฏธ์น ์ ์๋ ๊ฒ์ด ์๋๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ <Button>์ ํด๋ฆญํ๋ฉด <EditText>์๋ 4๊ฐ ์๋ 7+1 = 8์ด ๋ด๊ธด๋ค.
#2 ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ
#2-1 ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ด '์์'ํ๋ ๊ฒ
์ด์ฏค๋๋ฉด ์๋ฐฉํฅ(Two Way) ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ๋ํ ๊ทธ๋ฆผ์ด ๋ณด์ธ๋ค. ๋ฐ๋ก ๊ธฐ์กด์ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ์ถ๊ฐํด, View๋จ์์ ์ด๋ค์ง๋ ์ฌ์ฉ์์ ์
๋ ฅ์ ๋ด๋ถ ํ๋กํผํฐ์ ์์์ ์ผ๋ก ๋์
ํ๋ ๊ฒ์ด๋ค. ๋ง์ฝ, ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ์ฝ๋๋ฅผ ํ๋ก๊ทธ๋๋จธ๊ฐ ๋ช
์์ ์ผ๋ก ๋ฐํ ์ ๋๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ํํ์ผ ๊ฒ์ด๋ค.
...
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: MainActivityViewModel
override fun onCreate(savedInstanceState: Bundle?) {
...
binding.countText.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
// <EditText>์ ๋ด๊ธด ๊ฐ์ ๋ณํ๊ฐ ์๊ธธ ๋ ์ํํ ์ผ
}
override fun afterTextChanged(s: Editable?) {
// <EditText>์ ๋ํ ์ฌ์ฉ์์ ์
๋ ฅ์ด ๋๋ฌ์ ๋ ์ํํ ์ผ
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
// <EditText>์ ๋ํ ์ฌ์ฉ์์ ์
๋ ฅ์ด ๋ค์ด์ค๊ธฐ ์ง์ ์ ํ ์ผ
}
})
}
}
์ด๋ฌํ ์ฝ๋๋ฅผ ์์์ ์ผ๋ก ์ํํ๋ ๊ฒ ๋ฐ๋ก ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ด๋ค.
#2-2 ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ๊ตฌํํ๊ธฐ ์ํด ์ฐธ์กฐํ ์น์ฌ์ดํธ
์๋ฐฉํฅ ๋ฐ์ดํฐ ๊ฒฐํฉ | Android ๊ฐ๋ฐ์ | Android Developers
์๋ฐฉํฅ ๋ฐ์ดํฐ ๊ฒฐํฉ ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ์ค์ ์ ๊ธฐ์ค์ผ๋ก ์ฝํ ์ธ ๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฅํ์ธ์. ๋ค์๊ณผ ๊ฐ์ด ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๊ฒฐํฉ์ ์ฌ์ฉํ๋ฉด ์์ฑ์ ๊ฐ์ ์ค์ ํ๊ณ ์ด ์์ฑ์ ๋ณ๊ฒฝ์ ๋ฐ
developer.android.com
#3 ~ #5์ ๋ชจ๋ ์ฝ๋๋ ์ ๋งํฌ ๊ทธ๋ฆฌ๊ณ ๊ตฌ๊ธ ๊ณต์ ์ํ์ ์ฐธ์กฐํ์ฌ ์งฐ๋ค.
์ด์ ๋ถํฐ ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ์ฌ์ฉํด๋ณธ๋ค. ๋ณธ ๊ฒ์๊ธ์์ ์ด 3๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ๊ตฌํํ๋ค.
#3 Converter ์ด์ฉ (๋ฐฉ๋ฒ 1)
#3-1 Project ์์ค์ build.gradle.kts์ KSP(์ด๋ ธํ ์ด์ ๋ฌธ๋ฒ ์ฌ์ฉ์ ์ํ API) ํ๋ฌ๊ทธ์ธ ์ถ๊ฐ
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
...
id("com.google.devtools.ksp") version "1.9.0-1.0.13" apply false
}
KSP GitHub ํ์ด์ง์์ ํ๋ก์ ํธ์ Kotlin ๋ฒ์ ์ ๋ง๋ KSP ๋ฒ์ ์ ์ ํํด plugins { ... }์ ์ถ๊ฐํ๋ค.

Kotlin์ ๋ฒ์ ์ ์๋๋ก์ด๋ ์คํ๋์ค ์ฐฝ์ [File] - [Settings] - [Languages & Frameworks] - [Kotlin]์์ ํ์ธํ ์ ์๋ค.
#3-2 Module ์์ค์ build.gradle.kts์ KSP๋ฅผ ์ฌ์ฉํ๊ฒ ์ค์
plugins {
...
id("com.google.devtools.ksp")
id("org.jetbrains.kotlin.kapt")
}
android {
...
}
dependencies {
...
}
kapt๋ KSP์ ๊ตฌ๋ฒ์ ์ด๋ค. ํ์ง๋ง, ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ ์ด๋
ธํ
์ด์
์ฌ์ฉ์ ์ํด์๋ kapt๊ฐ ์ฌ์ ํ ํ์ํ๋ค๊ณ ํ๋ค. ๊ทธ๋์ kapt๋ plugins { ... }์ ๋ฃ๋๋ค.
#3-3 MyConverter.kt ๋ง๋ค๊ธฐ
// package com.example.twowaybindingusingconverter
import android.widget.EditText
import androidx.databinding.InverseMethod
object MyConverter {
@InverseMethod("stringToInt")
@JvmStatic
fun intToString(
view: EditText, value: Int
): String {
// ์ฌ์ฉ์๊ฐ ์์๋ฅผ ์
๋ ฅํ ๋, EditText.text๊ฐ "ํ" or "-ํ"์ด ๋๋ ์๊ฐ "0ํ"๋ก ๊ฐฑ์ ๋์ง ์๊ฒ ํ๊ธฐ ์ํ if๋ฌธ
if (value == 0) {
return view.text.toString()
}
return value.toString() + "ํ"
}
@JvmStatic
fun stringToInt(
view: EditText, value: String
): Int {
return value.replace("ํ", "").toIntOrNull() ?: 0
}
}
intToString()์ ViewModel์์ ๋ณด๋ธ ์ด๋ค ๋ณ์๋ฅผ View์ ํ์(ViewModel โ View)ํ ๋ ์๋์ผ๋ก ์ฌ์ฉ๋๋ ํจ์๋ค. stringToInt()๋ ๊ทธ ๋ฐ๋(View โ ViewModel)๋ค. stringToInt()๋ View์์ ์ฌ์ฉ์๊ฐ ์
๋ ฅํ ๊ฐ์ ์๋์ผ๋ก ViewModel์ ์ด๋ค ๋ณ์์๊ฒ ์ฌํ ๋นํ๋ค. ํ๋ก๊ทธ๋๋จธ๋ ViewModel โ View์ ์ฌ์ฉ๋๋ ํจ์์ธ intToString()๋ง์ ๋ช
์์ ์ผ๋ก ์ฌ์ฉํ๋ค. View โ ViewModel์ ๋ด๋นํ๋ stringToInt()๋ ์์์ ์ผ๋ก ์คํ๋๋ค. KSP๋ stringToInt()๊ฐ intToString()์ ๋ฐ๋ ์ญํ ์์ ์ด๋ป๊ฒ ์๋ณํ๋๊ฐ? ๋ฐ๋ก @InverseMethod("stringToInt") ์ด๋
ธํ
์ด์
์ ์๋ณํด์๋ค. ๋ค์์ MyConverter์ ๋ฉ์๋๋ค์ด View(activity_main.xml)์์ ์ฌ์ฉ๋๋ ๋ชจ์ต์ด๋ค.
<EditText>์ ์ซ์๋ง ๋ฉ๊ทธ๋ฌ๋ ํ์ํ๊ธฐ์ ํ์ ํ ๊ฒ ๊ฐ์์, ์ซ์ ์ค๋ฅธ์ชฝ์ "ํ"๋ฅผ ๋ถ์ด๋ ๋ก์ง๋ ๊ตฌํํด ๋ฃ์๋ค.
#3-4 activity_main.xml์์ Converter ์ฌ์ฉ
<?xml version="1.0" encoding="utf-8"?>
<layout ...>
<data>
<import type="com.example.twowaybindingusingconverter.MyConverter" />
<variable
name="myViewModel"
type="com.example.twowaybindingusingconverter.MainActivityViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout ...>
<Button ... />
<EditText
android:id="@+id/countText"
...
android:text="@={MyConverter.intToString(countText, myViewModel.getCurrentCount())}"
... />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
๋จผ์ , <EditText>์ android:text ์์ฑ์ ์๋ ๋ฐ์ธ๋ฉ ์์ @{ ... }๋ฅผ @={ ... }๋ก ๋ณ๊ฒฝํ๋ค. ๊ทธ๋์ผ๋ง ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ด ํ์ฉ๋๋ค. <data> ํ๊ทธ ์์ MyConverter๋ฅผ importํ๋ค. ๊ทธ๋ฆฌ๊ณ @={ ... } ์์ intToString()๋ฅผ ์ฌ์ฉํ ์ฝ๋๋ฅผ ๋ฃ๋๋ค. ์ฐธ๊ณ ๋ก, id๋ฅผ count_text์ ๊ฐ์ด ์ค๋ค์ดํฌ ํ๊ธฐ๋ฒ์ผ๋ก ์ง์ผ๋ฉด @={ ... } ์์์ id๊ฐ ์ธ์๋์ง ์๋๋ค. ๋ฐ๋ผ์ id๋ ๋ฐ๋์ ์นด๋ฉ ํ๊ธฐ๋ฒ์ ์ฌ์ฉํด ์ง์ด์ผ ํ๋ค.
#4 BindingAdapter ๋ฐ InverseBindingAdapter ์ด์ฉ (๋ฐฉ๋ฒ 2)
#4-1 ์ฌ์ ์์
KSP API์ kapt API๋ฅผ ํ๋ฌ๊ทธ์ธ์ ์ถ๊ฐํ๋ค. (#3-1๊ณผ #3-2 ์ฐธ์กฐ)
#4-2 MyBindingAdapter.kt ๋ง๋ค๊ธฐ
// package com.example.twowaybindingusingcustomattributes
import android.widget.EditText
import androidx.databinding.BindingAdapter
import androidx.databinding.InverseBindingAdapter
object MyBindingAdapters {
@BindingAdapter("android:text")
@JvmStatic
fun setCountText(editText: EditText, value: Int?) {
// ์ฌ์ฉ์๊ฐ ์์๋ฅผ ์
๋ ฅํ ๋, EditText.text๊ฐ "ํ" or "-ํ"์ด ๋๋ ์๊ฐ "0ํ"๋ก ๊ฐฑ์ ๋์ง ์๊ฒ ํ๊ธฐ ์ํ if๋ฌธ
if ((editText.text.toString().replace("ํ", "").toIntOrNull() ?: 0) == (value ?: 0)) {
return
}
editText.setText(value?.toString() + "ํ")
}
@InverseBindingAdapter(attribute = "android:text")
@JvmStatic
fun getCountText(editText: EditText): Int {
return editText.text.toString().replace("ํ", "").toIntOrNull() ?: 0
}
}
/*
์์ ์ฝ๋๋ (https://developer.android.com/topic/libraries/data-binding/two-way?hl=ko)์ ์๋ ์ฝ๋๋ฅผ ์ฐธ์กฐํ ์ฝ๋๋ค.
๊ทธ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
์๋ฅผ ๋ค์ด MyView๋ผ๋ ๋ง์ถค ๋ทฐ์ "time" ์์ฑ์ ์๋ฐฉํฅ ๋ฐ์ดํฐ ๊ฒฐํฉ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ,
@BindingAdapter("time")
@JvmStatic fun setTime(view: MyView, newValue: Time) {
// Important to break potential infinite loops.
if (view.time != newValue) {
view.time = newValue
}
}
@InverseBindingAdapter("time")
@JvmStatic fun getTime(view: MyView) : Time {
return view.getTime()
}
*/
Converter์ ๋ฌ๋ฆฌ BindingAdapter ๋ฐ InverseBindingAdatper๋ ๋ทฐ ์์ฒด์ ์ ์ฉ๋๋ ๋ฆฌ์ค๋๋ค. setCountText()์ getCountText()๋ android:text ์์ฑ์ ๊ฐ์ง ๊ฐ์ฒด๊ฐ ๋ณํ๋ฅผ ๊ฐ์งํด ์๋์ผ๋ก ์คํ๋๋ค. Converter์ ๋นํด ์ผ๊ด์ ์ธ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ด ๊ฐ๋ฅํ๋ค. '์ผ๊ด์ '์ด๋ผ๋ ์ฅ์ ์, '์ธ๋ถ์ ' ์ค์ ์ด ์ด๋ ต๋ค๋ผ๋ ๋จ์ ์ผ๋ก ์์ฉํ ์๋ ์๊ฒ ์ง๋ง ๋ง์ด๋ค. ์ฝ๋ ์๋ซ๋ถ๋ถ์ ์๋ ์ฃผ์์ฒ๋ผ ์ฌ์ฉ์ ์ ์ View์๋ ์ฌ์ฉํ ์ ์๋ค.
#4-3 activity_main.xml์์ BindingAdapter ๋ฐ InverseBindingAdapter ์ด์ฉ
<?xml version="1.0" encoding="utf-8"?>
<layout ...>
<data>
<import type="com.example.twowaybindingusingcustomattributes.MyBindingAdapters" />
<variable
name="myViewModel"
type="com.example.twowaybindingusingcustomattributes.MainActivityViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout >
<Button ... />
<EditText
...
android:text="@={(myViewModel.getCurrentCount())}"
... />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<EditText>์ android:text ์์ฑ์ ์๋ ๋ฐ์ธ๋ฉ ์์ @{ ... }๋ฅผ @={ ... }๋ก ๋ณ๊ฒฝํ๊ณ , <data> ํ๊ทธ ์์ MyBindingAdapter๋ฅผ importํ๋ค. import๋ ์๊ฐ๋ถํฐ activity_main.xml์์ android:text ์์ฑ์ด ๋ณํ๋ ๋๋ง๋ค ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํด ๊ทธ ๋ณํ๊ฐ ๊ฐ์ง๋๋ค.
#5 'Built-In' BindingAdapter ๋ฐ InverseBindingAdapter ์ด์ฉ (๋ฐฉ๋ฒ 3)
#5-1 ์ฌ์ ์์ ํ์์์
์ฌ์ค <TextView>์ android:text ์์ฑ์ ์์ฒด์ ์ผ๋ก '๊ธฐ๋ณธ์ ์ธ' ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ์ง์ํ๋ค. ์ด๋ฏธ ๊ตฌํ๋์ด Built-In๋ BindingAdapter ๋ฐ InverseBindingAdapter๊ฐ ์๋ค๋ ์ด์ผ๊ธฐ๋ค. <TextView>์ ์์์ธ <EditText>์๋ ๋ง์ฐฌ๊ฐ์ง์ผ ๊ฒ์ด๋ค. ์ฆ, #4์ฒ๋ผ MyBindingAdapter๋ฅผ ๋ง๋ค ํ์๋ ์๊ณ ๊ทธ ์์ ์๋ ์ด๋
ธํ
์ด์
๋ฌธ๋ฒ ๋ํ ์ฐ์ง ์์๋ ๋๋ค. ๊ทธ๋์ #3 ๋ฐ #4์์ ํ๋ KSP API์ kapt API๋ฅผ ํ๋ฌ๊ทธ์ธ์ ์ถ๊ฐํ ํ์๊ฐ ์๋ค.
๋ค๋ง, Built-In๋ ๊ฒ์ ์ด๋๊น์ง๋ '๊ธฐ๋ณธ์ ์ธ' ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ด๋ผ๋ ๊ฒ์ ๊ธฐ์ตํ์. #4์์์ ๋ฌ๋ฆฌ ์ฌ์ฉ์ ์ ์ View์๋ ์ฌ์ฉํ ์ ์๋ค. ์ ํ์ ์ธ ์ฉ๋๋ก๋ง ์ฌ์ฉ๋๋ค๋ ๊ฒ์ ๋จ์ ์ด์ง๋ง, ๋ณธ ๊ฒ์๊ธ์ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ ๊ตฌํ ๋ฐฉ์ ์ค์์๋ ๊ทธ ๊ตฌํ ๋์ด๋๊ฐ ์ ์ผ ๋ฎ๋ค๋ ์ฅ์ ์ด ์๋ค.
#5-2 MainActivityViewModel.kt ์์
// package com.example.twowaybindingusingbuiltinattributes
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class MainActivityViewModel : ViewModel() {
private var count: MutableLiveData<String> = MutableLiveData("0ํ")
fun getCurrentCount(): MutableLiveData<String> {
return count
}
fun updateCount() {
val valueInt = count.value?.replace("ํ", "")?.toIntOrNull() ?: 0
count.value = (valueInt + 1).toString() + "ํ"
}
}
count ๋ณ์์ ์ ๋ค๋ฆญ์ String์ผ๋ก ๋ฐ๊พผ๋ค. ๊ทธ์ ๋ง์ถฐ updateCount() ํจ์์ ๋ด์ฉ๋ ์๋ณธ๋ค. ์ ์ด๋ฌ๋๊ฑธ๊น? ๋ฐ๋ก Built-In๋ BindingAdapter ๋ฐ InverseBindingAdapter๊ฐ '๊ธฐ๋ณธ์ ์ธ' ๊ธฐ๋ฅ๋ง์ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ฆ, ์๋ฅผ ๋ค์ด Int โ String์ผ๋ก ๋ฐ๊พธ๊ฑฐ๋ String โ Int๋ก ๋ฐ๊พธ๋ ๊ธฐ๋ฅ์ด ์๋ค. ์ค์ง String โ String ๋ง ๊ฐ๋ฅํ๋ค. ๊ทธ๋์ count์ ์ ๋ค๋ฆญ์ ๊ทธ์ ๋ง์ถ๋ ๊ฒ์ด๋ค. ๋ง์ฝ, ๋ณต์กํ ๋ณํ์ ๊ตฌํํ๋ ค๋ฉด ์ฌ์ฉ์ ์ ์ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ ์ฆ #3 ๋๋ #4์ ๋ฐฉ์์ ์ด์ฉํด์ผ ํ๋ค.
#5-3 activity_main.xml ์์
<?xml version="1.0" encoding="utf-8"?>
<layout ...>
...
<androidx.constraintlayout.widget.ConstraintLayout ...>
<Button ... />
<EditText
...
android:text="@={(myViewModel.getCurrentCount())}"
... />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<EditText>์ android:text ์์ฑ์ ์๋ ๋ฐ์ธ๋ฉ ์์ @{ ... }๋ฅผ @={ ... }๋ก ๋ณ๊ฒฝํ๋ฉด ๋์ด๋ค. ์ถ๊ฐ๋ก count๋ ์ด์ String์ด๋ toString()๋ ์ ๊ฑฐํ๋ค.
#6 ์๋ ํ์ธ - ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ

#7 ์์ฝ
๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ํตํด Activity๊ณผ View์ ๊ฒฐํฉ๋๋ฅผ ์ค์๋ ๊ฒ์ฒ๋ผ, ์๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ ๋ํ (#2-1์ MainActivity.kt ์ฝ๋๋ฅผ ์์์ ์ผ๋ก ์ํํ๋ฉด์) Activity๊ณผ View์ ๊ฒฐํฉ๋๋ฅผ ์ค์ธ๋ค.
#8 ์์ฑ๋ ์ฑ
#8-1 Converter ์ด์ฉ (๋ฐฉ๋ฒ 1)
android-practice/live-data/TwoWayBindingUsingConverter at master ยท Kanmanemone/android-practice
Contribute to Kanmanemone/android-practice development by creating an account on GitHub.
github.com
#8-2 BindingAdapter ๋ฐ InverseBindingAdapter ์ด์ฉ (๋ฐฉ๋ฒ 2)
android-practice/live-data/TwoWayBindingUsingCustomAttributes at master ยท Kanmanemone/android-practice
Contribute to Kanmanemone/android-practice development by creating an account on GitHub.
github.com
#8-3 'Built-In' BindingAdapter ๋ฐ InverseBindingAdapter ์ด์ฉ (๋ฐฉ๋ฒ 3)
android-practice/live-data/TwoWayBindingUsingBuiltInAttributes at master ยท Kanmanemone/android-practice
Contribute to Kanmanemone/android-practice development by creating an account on GitHub.
github.com
'๊นจ์ ๊ฐ๋ ๐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] Activity์ ์๋ช ์ฃผ๊ธฐ (0) | 2024.01.23 |
---|---|
[Android] MVVM ๊ตฌ์กฐ ํ๋์ ๋ณด๊ธฐ (0) | 2024.01.22 |
[Android] LiveData - ์์์ ์ผ๋ก '๊ด์ฐฐ'ํ๊ธฐ (0) | 2024.01.19 |
[Android] ViewModel - View์ ๊ฐ์ฒด(ViewModel) ์ ๋ฌ (0) | 2024.01.18 |
[Android] LiveData - ๊ธฐ์ด (0) | 2024.01.16 |