티스토리 뷰
객체에 대한 바인딩을 찾아본 이유 : databinding을 적용중에 있다. 그런데 xml 에서 ViewModel의 객체를 바인딩했는데, 객체의 내부 값이 변경되었음에도 불구하고 화면에 적용되지 않았다. 그래서 한참을 찾아보던 중에 객체에 대한 바인딩의 경우, 내부 값이 변경됨을 자동으로 알 수 없다는 것이었다. 따라서 따로 해당 객체 내의 특정 필드 값이 변경되었을 때, 변경됨을 직접 알려줘야 한다.
https://developer.android.com/topic/libraries/data-binding/observability?hl=ko#observable_objects
참조 내용에는 직접 데이터 바인딩을 설정해야 하는 몇 가지 경우에 대하여 얘기하고 있다.
나느 그중에서 식별 가능한 객체에 대해서 적용한다.
객체의 속성 값이 변경되어 이를 알리고 싶은 경우 변경사항 알림을 받을 리스너를 등록해야 한다.
즉, 리스너를 데이터 객체에 제공하여 객체 내의 데이터가 변경되면 알려주도록 한다는 것이다.
속성 변경의 알림을 위한 리스너는 Observable 인터페이스를 구현하는 클래스를 사용하면 된다. 그러나 좀 더 쉽게 리스너를 등록할 수 있도록 안드로이드의 databinding 라이브러리에서는 BaseObservable 클래스를 제공한다.
이를 이용하여, 변경여부에 따른 알림을 원하는 속성의 setter에 notifyPropertyChanged()메서드를 등록하고, getter에는 @Bindable을 할당하여, 변경에 따른 알림을 받을 수 있도록 한다.
databinding은 데이터 결합 시 사용되는 리소스 ID를 포함하는 BR 클래스를 생성하며, notifyPropertyChanged() 메서드의 파라미터로 제공한다.
(BR 클래스 : 데이터 결합에 사용되는 binding 객체의 ID를 가짐)
(속성의 getter에 @Bindable을 설정하면, BR 클래스 내에 해당 속성의 ID값이 부여되며, 이후 setter를 통해 해당 속성 값이 변경시 notifyPropertyChanged를 사용하여 해당 속성이 변경됨을 알린다.)
※만약 BaseObservable 클래스를 상속받을 수 없을 경우, PropertyChangeRegistry 객체를 사용하여 Observable 인터페이스를 구현함으로써, 리스너를 등록하고 알림을 제공할 수 있도록 한다.
사용방법
: YouTubeItem 객체에서 title이 변경되었을 때, 변경된 값을 알리고 싶은 경우
1. BaseObservable 클래스를 상속 받는다.
2. 변경여부를 알리고 싶은 속성에 대하여, getter - @Bindable, setter - notifyPropertyChanged 를 설정한다.
※ @Bindable 을 속성에 할당하면, BR 클래스 내에 해당 속성의 ID가 할당되며, 관찰 대상이 된다.
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.databinding;
import androidx.databinding.Observable.OnPropertyChangedCallback;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The Bindable annotation should be applied to any getter accessor method of an
* {@link Observable} class. Bindable will generate a field in the BR class to identify
* the field that has changed.
* <p>
* When applied to an accessor method, the Bindable annotation takes an optional
* list of property names that it depends on. If there is a change notification of any of the
* listed properties, this value will also be considered dirty and be refreshed. For example:
* <p><pre>
* <code>@Bindable
* public void getFirstName() { return this.firstName; }
*
* @Bindable
* public void getLastName() { return this.lastName; }
*
* @Bindable({"firstName", "lastName"}}
* public void getName() { return this.firstName + ' ' + this.lastName; }
* </code></pre>
* <p>
* Whenever either {@code firstName} or {@code lastName} has a change notification, {@code name}
* will also be considered dirty. This does not mean that
* {@link OnPropertyChangedCallback#onPropertyChanged(Observable, int)} will be notified for
* {@code BR.name}, only that binding expressions containing {@code name} will be dirtied and
* refreshed.
*
* @see OnPropertyChangedCallback#onPropertyChanged(Observable, int)
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) // this is necessary for java analyzer to work
public @interface Bindable {
String[] value() default {};
}
'android' 카테고리의 다른 글
[android] The style on this component requires your app theme to be Theme.MaterialComponents 해결 방법 (+Material Design 사이트 ) (0) | 2020.09.02 |
---|---|
[android] AlarmManager 등록 확인 방법 (0) | 2020.08.31 |
[android] SingleLiveEvent (0) | 2020.07.27 |
[android] data binding error 문제 해결 방법 (0) | 2020.07.18 |
[Google I/O] Fun with LiveData (Android Dev Summit '18) 정리 (0) | 2020.07.13 |