양방향 데이터 바인딩

나고수·2022년 5월 22일
1

1일1공부

목록 보기
42/68
post-custom-banner

기본적으로 제공하는 양방향 데이터 바인딩 속성

//activity_main.xml
<?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.myapplication.MyViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <androidx.appcompat.widget.AppCompatEditText
            android:id="@+id/edittext"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={viewModel.text}" 👈
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private val viewModel: MyViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView<ActivityMainBinding?>(this, R.layout.activity_main)
            .apply {
                viewModel = this@MainActivity.viewModel
                lifecycleOwner = this@MainActivity
            }
        viewModel.text.observe(this) {
            Log.d("LOGGING", it) //editText 값이 viewModel.text 에 잘 들어간다면, 여기서 observe 가능
        }
    }
}

class MyViewModel : ViewModel() {
    val text = MutableLiveData<String>().apply { value = "" } //초기갑 세팅 필요 - 안하면 xml에서 해당값 처음 읽어올때, 읽어올 값이 없어서 getter 오류남
}

커스텀 양방향 데이터 바인딩

object BindingAdapter {
    //1
    @BindingAdapter("android:text") 
    //안드로이드 기본 속성이면 이렇게 쓰면 되고, 
    //custom 속성이면 그 속성 이름을 적어주면 됩니다.
    @JvmStatic
    fun setTime(view: EditText, newValue: String) {
        // 값이 변경될 때 업데이트하는 메서드
		// viewModel.text 값을 view에
        // 단방향 데이터바인딩 할때 사용하는 기본 bindingAdapter
        // Important to break potential infinite loops.
        // 2>3>1>2>3>1... 무한반복에 빠지지 않기 위해서 체크 
        if (view.text.toString() != newValue) { 
            view.setText(newValue)
        }
    }

    //2
    @BindingAdapter("android:textAttrChanged") //[my속성]AttrChanged
    @JvmStatic
    fun setListeners(
        view: EditText,
        attrChange: InverseBindingListener // 이 매개변수를 통해 속성이 변경되었음을 알림 -> @InverseBindingAdapter 호출
    ) {
        attrChange.onChange()
    }

    //3
    @InverseBindingAdapter(attribute = "android:text") //뷰에서 값을 읽는 메서드
	// view값을 viewModel.text에
    //  @InverseBindingAdapter(attribute =  "android:text", event = "android:textAttrChanged")
    @JvmStatic
    fun getTime(view: EditText): String {
        return view.text.toString()
    }
}
<androidx.appcompat.widget.AppCompatEditText
            android:text="@={viewModel.text}"
            android:id="@+id/edittext"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
profile
되고싶다
post-custom-banner

0개의 댓글