관찰 가능한 데이터 객체로 작업

관측 가능성은 객체가 데이터 변경을 다른 사용자에게 알릴 수 있는 기능을 의미합니다. 데이터 결합 라이브러리를 사용하면 객체, 필드 또는 컬렉션을 식별 가능하도록 만들 수 있습니다.

데이터 결합에 모든 객체를 사용할 수 있지만 객체를 수정해도 UI가 자동으로 업데이트되지는 않습니다. 데이터 결합을 사용하여 데이터 변경 시 리스너라고 하는 다른 객체에 알리는 기능을 데이터 객체에 부여할 수 있습니다. 식별 가능한 클래스에는 세 가지 유형, 즉 필드, 컬렉션, 객체가 있습니다.

이러한 관찰 가능한 데이터 객체 중 하나가 UI에 결합되고 데이터 객체의 속성이 변경되면 UI가 자동으로 업데이트됩니다.

식별 가능한 필드

클래스에 속성 몇 개만 있는 경우 Observable 인터페이스를 구현하는 클래스를 만들지 않아도 됩니다. 이 경우 일반 Observable 클래스와 다음과 같은 프리미티브 관련 클래스를 사용하여 필드를 식별 가능하게 만들 수 있습니다.

식별 가능한 필드는 단일 필드가 있는 독립적인 식별 가능한 객체입니다. 프리미티브 버전은 액세스 작업 중에 박싱 및 언박싱을 방지합니다. 이 메커니즘을 사용하려면 다음 예와 같이 자바 프로그래밍 언어로 public final 속성을 만들거나 Kotlin으로 읽기 전용 속성을 만듭니다.

Kotlin

class User {
    val firstName = ObservableField<String>()
    val lastName = ObservableField<String>()
    val age = ObservableInt()
}

Java

private static class User {
    public final ObservableField<String> firstName = new ObservableField<>();
    public final ObservableField<String> lastName = new ObservableField<>();
    public final ObservableInt age = new ObservableInt();
}

필드 값에 액세스하려면 set()get() 접근자 메서드를 사용하거나 Kotlin 속성 문법을 사용합니다.

Kotlin

user.firstName = "Google"
val age = user.age

Java

user.firstName.set("Google");
int age = user.age.get();

식별 가능한 컬렉션

일부 앱은 동적 구조를 사용하여 데이터를 보유합니다. 관찰 가능한 컬렉션을 사용하면 키를 사용하여 이러한 구조에 액세스할 수 있습니다. ObservableArrayMap 클래스는 다음 예와 같이 키가 String과 같은 참조 유형일 때 유용합니다.

Kotlin

ObservableArrayMap<String, Any>().apply {
    put("firstName", "Google")
    put("lastName", "Inc.")
    put("age", 17)
}

Java

ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
user.put("firstName", "Google");
user.put("lastName", "Inc.");
user.put("age", 17);

다음 예와 같이 레이아웃에서 문자열 키를 사용하여 지도를 찾을 수 있습니다.

<data>
    <import type="android.databinding.ObservableMap"/>
    <variable name="user" type="ObservableMap&lt;String, Object&gt;"/>
</data>
…
<TextView
    android:text="@{user.lastName}"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
<TextView
    android:text="@{String.valueOf(1 + (Integer)user.age)}"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

ObservableArrayList 클래스는 다음과 같이 키가 정수일 때 유용합니다.

Kotlin

ObservableArrayList<Any>().apply {
    add("Google")
    add("Inc.")
    add(17)
}

Java

ObservableArrayList<Object> user = new ObservableArrayList<>();
user.add("Google");
user.add("Inc.");
user.add(17);

다음 예와 같이 레이아웃에서 색인을 통해 목록에 액세스할 수 있습니다.

<data>
    <import type="android.databinding.ObservableList"/>
    <import type="com.example.my.app.Fields"/>
    <variable name="user" type="ObservableList&lt;Object&gt;"/>
</data>
…
<TextView
    android:text='@{user[Fields.LAST_NAME]}'
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
<TextView
    android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

식별 가능한 객체

Observable 인터페이스를 구현하는 클래스를 사용하면 관찰 가능한 객체의 속성 변경 알림을 받으려는 리스너를 등록할 수 있습니다.

Observable 인터페이스에는 리스너를 추가하고 삭제하는 메커니즘이 있지만 알림이 전송되는 시점은 개발자가 결정합니다. 더 쉽게 개발할 수 있도록 데이터 결합 라이브러리는 리스너 등록 메커니즘을 구현하는 BaseObservable 클래스를 제공합니다. BaseObservable를 구현하는 데이터 클래스는 속성이 변경될 때 알리는 역할을 합니다. 이렇게 하려면 다음 예와 같이 getter에 Bindable 주석을 할당하고 setter에서 notifyPropertyChanged() 메서드를 호출합니다.

Kotlin

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)
        }
}

Java

private static class User extends BaseObservable {
    private String firstName;
    private String lastName;

    @Bindable
    public String getFirstName() {
        return this.firstName;
    }

    @Bindable
    public String getLastName() {
        return this.lastName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        notifyPropertyChanged(BR.firstName);
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
        notifyPropertyChanged(BR.lastName);
    }
}

데이터 결합은 모듈 패키지에 BR라는 클래스를 생성합니다. 이 클래스에는 데이터 결합에 사용되는 리소스의 ID가 포함됩니다. Bindable 주석은 컴파일 중에 BR 클래스 파일에 항목을 생성합니다. 데이터 클래스의 기본 클래스를 변경할 수 없는 경우 PropertyChangeRegistry 객체를 사용하여 Observable 인터페이스를 구현하여 리스너에 효율적으로 등록하고 리스너에 알릴 수 있습니다.

수명 주기 인식 객체

앱의 레이아웃은 데이터 변경사항을 UI에 자동으로 알리는 데이터 결합 소스에 결합할 수도 있습니다. 이렇게 하면 결합이 수명 주기를 인식하며 UI가 화면에 표시될 때만 트리거됩니다.

데이터 결합은 StateFlowLiveData를 지원합니다. 데이터 결합에서 LiveData를 사용하는 방법에 관한 자세한 내용은 LiveData를 사용하여 UI에 데이터 변경사항 알림을 참고하세요.

StateFlow 사용

앱에서 Kotlin을 코루틴과 함께 사용하는 경우 StateFlow 객체를 데이터 결합 소스로 사용할 수 있습니다. 결합 클래스와 함께 StateFlow 객체를 사용하려면 수명 주기 소유자를 지정하여 StateFlow 객체의 범위를 정의하세요. 다음 예에서는 결합 클래스가 인스턴스화된 후 활동을 수명 주기 소유자로 지정합니다.

class ViewModelActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        // Inflate view and obtain an instance of the binding class.
        val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)

        // Specify the current activity as the lifecycle owner.
        binding.lifecycleOwner = this
    }
}

아키텍처 구성요소에 레이아웃 뷰 결합에 설명된 대로 데이터 결합은 ViewModel 객체와 원활하게 작동합니다. 다음과 같이 StateFlowViewModel를 함께 사용할 수 있습니다.

class ScheduleViewModel : ViewModel() {

    private val _username = MutableStateFlow<String>("")
    val username: StateFlow<String> = _username

    init {
        viewModelScope.launch {
            _username.value = Repository.loadUserName()
        }
    }
}

다음 예와 같이 레이아웃에서 결합 표현식을 사용하여 상응하는 뷰에 ViewModel 객체의 속성과 메서드를 할당합니다.

<TextView
    android:id="@+id/name"
    android:text="@{viewmodel.username}" />

사용자의 이름 값이 변경될 때마다 UI가 자동으로 업데이트됩니다.

StateFlow 지원 사용 중지

Kotlin과 AndroidX를 사용하는 앱의 경우 StateFlow 지원이 데이터 결합에 자동으로 포함됩니다. 즉, 종속 항목을 아직 사용할 수 없는 경우 코루틴 종속 항목이 앱에 자동으로 포함됩니다.

build.gradle 파일에 다음을 추가하여 이 기능을 선택 해제할 수 있습니다.

Groovy

android {
    ...
    dataBinding {
        addKtx = false
    }
}

Kotlin

android {
    ...
    dataBinding {
        addKtx = false
    }
}

또는 gradle.properties 파일에 다음 줄을 추가하여 프로젝트에서 StateFlow를 전역적으로 사용 중지할 수 있습니다.

Groovy

android.defaults.databinding.addKtx = false

Kotlin

android.defaults.databinding.addKtx = false

추가 리소스

데이터 결합에 관한 자세한 내용은 다음을 참고하세요.

샘플

Codelab

블로그 게시물