본문 바로가기

[Android] DataBinding #2 - Observable Object/Field/Collection

DataBinding #2 - Observable Object/Field/Collection

 

 

INDEX

 

 

 

Observable

 

: DataBinding하면 POJO 값을 xml내 변수에 설정하여 xml에서 view가 변수의 값을 이용할 수 있습니다

첫 POJO변수 user를 설정할 때 view들이 user의 값을 사용하여 뷰에 표현을 하는데,

그 이후에 POJO를 수정에도 View에는 반영되지 않기 때문에, UI는 업데이트 되지 않습니다 

이러한 문제를 해결하기 위해 데이터가 변경될 때마다 변경을 알려주는 메커니즘(Observable)을 이용

 

: Observable Type의 여러 클래스들을 사용하는 방법이 있습니다

 

 


#01 Observable Object

: DataBinding에서 제공하는 Observable 인터페이스구현한 클래스를 의미합니다.

ObservableObject는 실시간 관찰이 가능한 객체로 getter/setter 등록이 가능합니다

직접 POJO클래스에 Observable 인터페이스를 구현(implement)하여 사용할 수 있지만

이미 구현되어있는 BaseObservable 클래스상속해서 POJO클래스를 사용하면 수월하게 사용이 가능

 

BaseObservable을 상속한 POJO클래스 사용방법

  1) Getter 메서드에 @Bindable 어노테이션(annotation) 추가

        : @Bindable 어노테이션 설정 필드는 컴파일 시 BR 클래스에 fieldId를 자동 생성

      getName, getEmail에 @Bindable이 붙어 컴파일 시 BR클래스에 name, email 필드가 자동 생성되고

        생성된 BR클래스 fieldId는 notifyPropertyChanged(int fieldId) 메서드의 파라미터로 사용

         (BR 클래스파일은 모듈 패키지 내에 생성)

   2) Setter 메서드notifyPropertyChanged(int fieldId) 메서드 추가, 속성 변경 알림

        : notifyPropertyChanged(int fieldId)는 해당 fieldId의 값이 변경되었음을 알리는 메서드

       fieldId는 @Bindable 애노테이션이 선언된 getter함수의 필드를 의미

: Observable 인터페이스 함수 notifyPropertyChanged(속성) 메서드 호출 시 해당 속성(프로퍼티)을

참조하는 View들은 변경알림을 받고 재참조를 하게되어 값이 변경되면 UI를 업데이트합니다

 


#02 Observable Field

: Observable 인터페이스를 구현한 POJO클래스가 아닌, ObservableField 프로퍼티를 이용하는 방법

Observable Fields단일 속성(Property)를 가진 Observable 객체로 POJO클래스에 public final 필드 생성

OBservableField 외에도 기본형들을 사용하는 Observable 프로퍼티들이 존재합니다

  • ObservableBoolean

  • ObservableByte

  • ObservableChar

  • ObservableShort

  • ObservableLong

  • ObservableFloat

  • ObservableDouble

  • ObservableParacelable

: ObservableField는 박싱/언박싱 방지를 위해 final(kotlin은 val)로 선언해야 합니다

ObservableField는 get() / set() 접근연산자로 update합니다

 

 

ObservableField 속성 Access 방법 (기존 setter/getter가 아닌 set() / get()접근자 메서드 사용)

: 기존 Setter/Getter 메서드가 아닌 set() / get() 접근자 메서드 사용

ObservableField 타입의 속성이여서 값 변경시 자동으로 View에 알림(notiy)를 줘서 UI업데이트 가능

Observable 인터페이스를 구현한 Observable Object와 달리 사용자가 notify 메서드 호출 필요가 없는 점

 

 


#03 Observable Collection

: Key와 Value로 이루어진 Map형태의 동적인 구조체도 ObservableArrayMap으로 제공

데이터 객체에 key 입력방식으로 엑세스가 가능하고,

key가 String 같은 참조형식일 경우 ObservableArrayMap이 유용합니다

 

  • ObservableArrayMap 인스턴스 생성 및 추가
ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
user.put("name", "홍길동");
user.put("age", 25);
user.put("email", "hong@gmail.com");
binding.setUser(user);
  • xml 레이아웃에서 String 키를 통해 Map에 접근
<data>
    <import type="androidx.databinding.ObservableMap"/>
    <variable name="user" type="ObservableMap&lt;String, Object&gt;"/>
</data>

....

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{user["name"]}'/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{user["email"]}' />


: <data>태그에 보면 <import> 태그와 변수의 type이 조금 다른걸 보실 수 있습니다

<import type="androidx.databinding.ObservableMap" />

   -> xml내에서 ObservableMap 타입의 클래스를 사용하기 위해 import함을 의미

<variable name="user" type="ObservableMap&lt;String, Object&gt;" />

    -> user 변수의 type은 ObservableMap<String, Object> 타입을 의미하는데

        xml에서는 '<>'의 특수문자를 그대로 사용할 수가 없어 해당 특수문자를 의미합니다

        &lt; = <    &gt; = > 의 특수문자를 의미

 

  • List 형태인 ObservableArrayList도 제공

     : key를 정수형태로 사용할 때는 ObservableArrayList가 유용합니다'

ObservableArrayList<Object> user = new ObservableArrayList<>();
user.add("홍길동");
user.add("hong@gmail.com");
binding.setUser(user);

<data>
    <import type="androidx.databinding.ObservableList"/>
    <variable name="user" type="ObservableList&lt;Object&gt;"/>
</data>

....

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{user[0]}'/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{user[1]}'/>