단방향 데이터 바인딩은 데이터 변경 사항이 모델에서 레이아웃으로 전달되는 구조다.
반면에 양방향 바인딩을 사용하면 레이아웃에서 데이터 변경 사항이 역방향으로도 전달되게 할 수 있다.
단방향 바인딩에서 바인딩 표현식은 "@{}"
구문을 사용하지만 양방향 바인딩에서는 "@={}"
구문을 사용한다.
데이터 변경에 반응하도록 레이아웃 변수는 Observable
인터페이스를 구현해야 한다.
일반적으로 데이터 바인딩 라이브러리에서 제공하는 BaseObservable
클래스를 상속받는다.
그리고 게터에 @Bindable
어노테이션을 추가한다.
커스텀 속성으로 양방향 바인딩
커스텀 속성에 대해 양방향 데이터 바인딩을 사용하려면 다음을 따른다.
MyView
라는 커스텀 뷰의 time
속성에 양방향 바인딩을 사용하고자 한다고 가정하자.
- 초기값을 설정하고 값이 변경될 때 업데이트하는 메서드(세터)에
@BindingAdapter
어노테이션을 추가한다.
@BindingAdapter("time") @JvmStatic fun setTime(view: MyView, newValue: Time) { if (view.time != newValue) { view.time = newValue } }
- 뷰에서 데이터를 가져오는 메서드(게터)에
@InverseBindingAdapter
어노테이션을 추가한다.
@InverseBindingAdapter("time") @JvmStatic fun getTime(view: MyView) : Time { return view.getTime() }
- 속성 값의 변경을 인식하는
InverseBindingListener
를 구현한다.
리스너를 설정하는 메서드에는@BindingAdapter
어노테이션을 추가하고 관련 속성 이름을 파라미터로 전달한다.@BindingAdapter("app:timeAttrChanged") @JvmStatic fun setListeners( view: MyView, attrChange: InverseBindingListener ) { /* 리스너 설정 */ }
컨버터
데이터 바인딩 변수를 뷰에 표시하기 전 타입 변환이 필요한 경우 컨버터 객체를 사용하면 된다.
양방향 바인딩을 사용하므로 필요한 타입으로 변환하는 메서드와 역변환하는 메서드가 필요하다.
둘 중 한 쪽에 @BindingMethod
어노테이션을 추가하고 나머지 한 쪽에는 @InverseBindingMethod
어노테이션을 추가하고 파라미터로 다른 메서드를 참조하면 된다.
무한 루프 방지
속성이 변경되면 @InverseBindingAdapter
가 추가된 메서드가 호출되어 백킹 프로퍼티에 값이 할당된다.
이로 인해 @BindingAdapter
가 추가된 메서드가 호출되고 @InverseBindingAdapter
가 추가된 메서드가 또 호출될 수 있다.
이는 무한 루프를 발생시킬 수 있기 때문에 @BindingAdapter
가 추가된 메서드에서 값을 비교해야 한다.
'Android' 카테고리의 다른 글
DataStore (0) | 2022.11.30 |
---|---|
Lifecycle (0) | 2022.11.11 |
데이터 바인딩 (3) : 바인딩 어댑터 (0) | 2022.11.03 |
데이터 바인딩 (2) : 이벤트 처리 / Observable (0) | 2022.11.01 |
데이터 바인딩 (1) : 기본 사용법 (0) | 2022.10.29 |