
저번에는 data class를 이용해서 객체를 만들어내고 객체안에 정보를 변수에 할당해서
레이아웃 파일 내에서 사용된 바인딩 표현식이 실제 데이터와 연결시켰다
이번에는 MyViewModel class를 생성해서 클릭했을 때 변화를 일으키는 함수를 만들어서
버튼 객체와 연결시켜줄 것이다
import androidx.databinding.ObservableField
import androidx.lifecycle.ViewModel
class MyViewModel: ViewModel() {
    val buttonText = ObservableField("Click Me")
    var cnt = 0
    fun onButtonClick() {
        buttonText.set("${cnt} 번째: Button Clicked!")
        cnt++
    }
}ObservableField는 데이터 바인딩을 통해 UI 요소와 관련된 데이터의 변경을 감지하고, 자동으로 UI를 업데이트하는 데 사용된다
ObservableField를 사용하여 buttonText 변수를 선언한 것은 데이터 바인딩을 통해 이 변수의 값을 변경하고, 연결된 UI 요소(예: 버튼과 TextView)에 자동으로 반영되도록 하기 위함이다
ObservableField를 사용하여 buttonText 값을 변경하면, 해당 값은 바인딩된 UI 요소에 자동으로 반영됩니다. 이때, buttonText의 값이 변경되면 @{viewModel.buttonText}와 같은 바인딩 표현식을 사용하여 연결된 UI 요소의 텍스트가 업데이트된다
따라서, "Click Me"는 초기 값으로 사용되며, ObservableField를 통해 해당 값이 변경되면 연결된 UI 요소에 반영된다
<?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>
        <variable
            name="viewModel"
            type="com.example.databinding_func_practice.MyViewModel" />
    </data>
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="200dp"
            android:text="@{viewModel.buttonText}"
            android:textSize="30dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="100dp"
            android:text="Change Text"
            android:textSize="20dp"
            android:onClick="@{() -> viewModel.onButtonClick()}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/text" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout><data> 안에 타입은 사용할 class 이름의 위치로 해준다
xtView는 MyViewModel.class에서 버튼을 클릭하기 전에 초기 값인
"Click Me"로 업데이트되고
MyViewModel.class 에 있는 onButtonClick() 함수를 사용해서
TextView의 데이터가 변경이된다면 ObservableField를 통해 UI가 업데이트된다
객체의 경우 android:onClick="@{() -> viewModel.onButtonClick()}"
{()-> ...} 데이터 바인딩 표현식(expression)의 구문으로, 클릭 이벤트나 다른 이벤트에 대한 액션을 정의하는 데 사용된다
@{() -> ...}는 람다 표현식(lambda expression)으로, 클릭 이벤트가 발생했을 때 실행할 코드를 정의합니다. 여기서 () ->는 파라미터가 없는 람다 함수를 나타냅니다. 이 부분에는 클릭 이벤트 발생 시 실행할 코드를 작성할 수 있다
예를 들어, 위의 코드에서 android:onClick="@{() -> viewModel.onButtonClick()}"는 버튼이 클릭되었을 때 viewModel 객체의 onButtonClick() 메서드를 호출하는 것을 나타낸다
이렇게 클릭 이벤트에 대한 액션을 람다 표현식으로 정의하면, 해당 액션이 클릭 이벤트와 바인딩되어 실행된다
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.example.databinding_func_practice.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var viewModel: MyViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
        viewModel = MyViewModel()
        binding.viewModel = viewModel
        binding.lifecycleOwner = this
    }
}binding 객체를 초기화하기 위해 DataBindingUtil.setContentView() 메서드를 사용합니다. 이 메서드는 지정된 레이아웃(R.layout.activity_main)을 사용하여 액티비티의 컨텐츠 뷰를 설정하고, 바인딩 클래스의 인스턴스를 반환한다
viewModel 객체를 초기화하고, binding.viewModel = viewModel 코드를 사용하여 데이터 바인딩을 통해 액티비티와 viewModel을 연결한다
이렇게 함으로써 바인딩 클래스의 변수와 viewModel 객체를 연결하여 데이터를 양방향으로 전달할 수 있다
마지막으로, binding.lifecycleOwner = this 코드를 사용하여 바인딩 클래스의 라이프사이클 소유자를 현재 액티비티로 설정한다
이렇게 하면 데이터 바인딩이 액티비티의 라이프사이클과 함께 동작하고,
액티비티의 라이프사이클 변화에 따라 자동으로 업데이트될 수 있습니다.
이렇게 binding과 viewModel을 초기화하고 데이터 바인딩을 설정한 후,
MainActivity의 onCreate() 메서드가 완료된다
이제 해당 액티비티는 데이터 바인딩을 사용하여 레이아웃과 액티비티의 로직을 연결할 수 있게 된다