Android/MVVM (based on AAC)

Databinding - ObservableField, BaseObservable

네모메모 2022. 8. 16. 00:34
반응형

ObservableField (@Android/Databinding)

: 객체를 observable(=관찰 가능)하게 만드는 wrapper 클래스.

 

- Android의 Databinding의 소속으로 DataBinding을 활성화해야 사용 가능

java.lang.Object
   ↳ android.databinding.BaseObservable
     ↳ android.databinding.ObservableField<T>

 

- 사용 : ViewModel에서 로직이 변경 시 UI(의 작은 부분)가 자동 업데이트되도록 하기 위해 사용 

- 사용법)

ㄴ> 생성 : 아래와 같은 방법으로 생성가능

       1) Observable Primitive타입클래스 ex) Observable<String>(), ObservableInt()

       2) Observable Collection타입클래스 ex) ObservableArrayMap<String, Any>()

       3) 리스너 등록 메커니즘을 구현하는 BaseObservable를 상속 ex) 아래 별도 기재

 

ㄴ> 값설정 : get() / set(T value)

public ObservableInt countObservableInt = new ObservableInt(0);
countObservableInt.set(countObservableInt.get() + 1);

 

ㄴ> 관찰 : Databinding으로 레이아웃 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.android.observableint.MyViewModel" />
    </data>
    ...
    
    
    <!-- 여기가 중요!! -->
	<TextView
		...
	 andorid:text="@{String.valueOf(viewmodel.countObservableInt)}" />

 


추가 활용)

BaseObservable

 - 사용 : Observable객체의 값이 변경될 때 알림을 받는 리스너를 등록 시 BaseObservable를 상속받는다!

 - 속성이 변경될 때 알려준다.

 

- 사용법

1. 생성 : BaseObservable를 상속받는 Observable데이터클래스 생성

    class User : BaseObservable() {

        @get:Bindable
        var firstName: String = ""
            set(value) {
                field = value
                notifyPropertyChanged(BR.firstName)
            }

        @get:Bindable
        var lastName: String = ""
            set(value) {
                field = value
                notifyPropertyChanged(BR.lastName)
            }
    }

 

 

2. Getter :  주석 '@Bindable'은 모든 getter 위에 써줘야 합니다

  ∵ Databinding에 사용된 리소스의 ID를 포함하는 모듈 패키지에 이름이 BR인 BR클래스를 생성하는데 
      @Bindable 주석을 통해 컴파일 시
필드 값이 변경되면 BR 클래스에 필드를 생성하여 반응합니다.

  +) BR 클래스 :  처리할 모든 반응 값을 저장하기 위해 데이터 바인딩에 의해 생성되는 클래스

data class ProfileUIModel(
    private val _name: String,
    private val _age: Int
): BaseObservable() {
    var name: String
        @Bindable get() = _name

ㄴ> 어노테이션 @Bindable, @get:Bindable

        @Bindable : 기본적인 getter위에 붙여주는 어노테이션

        @get:Bindable : getter에  @Bindable  을 합쳐버린 형태

// 아래 코드 1,2,3은 모두 동일하다.

// 1. @Bindable get() 버전
@get:Bindable
var userIds: MutableList<Long> = mutableListOf()
        private set(value) {
            field = value
            notifyPropertyChanged(BR.userIds)
        }

// 2. @Bindable 버전
var userIds: MutableList<Long> = mutableListOf()
    @Bindable get() = _userIds
    set(value) {
        field = value
        notifyPropertyChanged(BR.userIds)
    }
    
// 3. 자바버전
private ArrayList<Long> userIds = new ArrayList<>();

@Bindable
public ArrayList<Long> getUserIds() {
    return userIds;
}

public void setUserIds(ArrayList<Long> userIds) {
    this.userIds = userIds;
    notifyPropertyChanged(BR.selected);
}

 

 

3. Setter

: setter에서 notifyPropertyChanged(BR.필드명) 메서드를 호출해야 setter 작업이 완료됨

        notifyChange() : 이 인스턴스의 모든 속성이 변경되었음을 리스너에게 알립니다.

        notifyPropertyChanged(int fieldId) : 특정 속성이 변경되었음을 리스너에게 알립니다.

data class ProfileUIModel(
    private val _name: String,
    private val _age: Int
): BaseObservable() {
    var name: String
        @Bindable get() = _name
        
        // setter
        set(value) {
          _name = value
          notifyPropertyChanged(BR.name)
        }

 

 

4. 레이아웃 XML

: '<variable>'태그로 BaseObservable클래스 변수 선언하고,@{변수.필드값}으로 사용

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
    <data>
    	<!-- BaseObservable 클래스 선언 -->
        <variable
            name="item"
            type="com.sample.model.ProfileUIModel" 
            />
    </data>
    ...
 
 
 	 <!-- BaseObservable 클래스 데이터를 'android:text'에 사용 -->
     <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{item.name}"
            />
            
...

 

 

 


[출처]

https://developer.android.com/topic/libraries/data-binding/observability?hl=en#observable_objects

https://developer.android.com/topic/libraries/data-binding/observability?hl=en#observable_objects 

https://developer.android.com/reference/android/databinding/Bindable?hl=en#annotations 

https://medium.com/@jencisov/androids-data-binding-s-baseobservable-class-and-bindable-annotation-in-kotlin-1a5c6682a3c1

https://stackoverflow.com/questions/52394858/when-to-use-android-s-livedata-and-observable-field

https://stackoverflow.com/questions/53910028/what-is-getbindable-in-the-android-data-binding-code

 

https://altongmon.tistory.com/834

 

 

반응형