Bekerja dengan objek data yang dapat diamati

Kemampuan observasi mengacu pada kemampuan objek untuk memberi tahu orang lain tentang perubahan datanya. Library Data Binding memungkinkan Anda membuat objek, kolom, atau koleksi dapat diamati.

Anda dapat menggunakan objek apa pun untuk data binding, tetapi memodifikasi objek tidak otomatis menyebabkan UI diupdate. Anda dapat menggunakan data binding agar objek data dapat memberi tahu objek lain—yang disebut sebagai pemroses—saat datanya berubah. Ada tiga jenis class yang dapat diamati: kolom, koleksi, dan objek.

Saat salah satu objek data yang dapat diamati ini terikat ke UI dan properti objek data berubah, UI akan otomatis diupdate.

Kolom yang dapat diobservasi

Jika class Anda hanya memiliki beberapa properti, mungkin tidak sepadan dengan upaya untuk membuat class yang mengimplementasikan antarmuka Observable. Dalam hal ini, Anda dapat menggunakan class Observable generik dan class khusus primitif berikut agar kolom dapat diamati:

Kolom observable adalah objek observable mandiri yang memiliki satu kolom. Versi primitif menghindari boxing dan unboxing selama operasi akses. Untuk menggunakan mekanisme ini, buat properti public final dalam bahasa pemrograman Java atau properti hanya-baca di Kotlin, seperti ditunjukkan dalam contoh berikut:

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

Untuk mengakses nilai kolom, gunakan metode pengakses set() dan get() atau gunakan sintaksis properti Kotlin:

Kotlin

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

Java

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

Koleksi yang dapat diobservasi

Beberapa aplikasi menggunakan struktur dinamis untuk menampung data. Koleksi yang dapat diobservasi memungkinkan akses ke struktur-struktur ini menggunakan kunci. Class ObservableArrayMap berguna jika kunci adalah jenis referensi, misalnya String, seperti ditunjukkan dalam contoh berikut:

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

Dalam tata letak, Anda dapat menemukan peta menggunakan kunci string, seperti yang ditunjukkan pada contoh berikut:

<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"/>

Class ObservableArrayList berguna jika kunci adalah bilangan bulat, seperti berikut:

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

Dalam tata letak, Anda dapat mengakses daftar melalui indeks, seperti yang ditunjukkan pada contoh berikut:

<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"/>

Objek yang dapat diobservasi

Class yang menerapkan antarmuka Observable memungkinkan pendaftaran pemroses yang ingin diberi tahu tentang perubahan properti dari objek yang dapat diamati.

Antarmuka Observable memiliki mekanisme untuk menambahkan dan menghapus pemroses, tetapi Anda yang memutuskan kapan notifikasi dikirim. Untuk mempermudah pengembangan, Library Data Binding menyediakan class BaseObservable, yang menerapkan mekanisme pendaftaran pemroses. Class data yang menerapkan BaseObservable bertanggung jawab untuk memberi tahu kapan properti berubah. Caranya, tetapkan anotasi Bindable ke pengambil dan panggil metode notifyPropertyChanged() di penyetel, seperti ditunjukkan dalam contoh berikut:

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

Data binding menghasilkan class bernama BR dalam paket modul yang berisi ID semua resource yang digunakan untuk data binding. Anotasi Bindable menghasilkan entri dalam file class BR selama kompilasi. Jika class dasar untuk class data tidak dapat diubah, Anda dapat mengimplementasikan antarmuka Observable menggunakan objek PropertyChangeRegistry untuk mendaftarkan dan memberi tahu pemroses secara efisien.

Objek yang mendukung siklus proses

Tata letak di aplikasi Anda juga dapat mengikat ke sumber data binding yang otomatis memberi tahu UI tentang perubahan data. Dengan demikian, binding Anda berbasis siklus proses dan hanya dipicu saat UI terlihat di layar.

Data binding mendukung StateFlow dan LiveData. Untuk mengetahui informasi selengkapnya tentang penggunaan LiveData dalam data binding, lihat Menggunakan LiveData untuk memberi tahu UI tentang perubahan data.

Menggunakan StateFlow

Jika aplikasi Anda menggunakan Kotlin dengan coroutine, Anda dapat menggunakan objek StateFlow sebagai sumber data binding. Untuk menggunakan objek StateFlow dengan class binding, tentukan pemilik siklus proses untuk menentukan cakupan objek StateFlow. Contoh berikut menetapkan aktivitas sebagai pemilik siklus proses setelah class binding dibuat instance:

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

Seperti yang dijelaskan dalam Mengikat tampilan tata letak ke Komponen Arsitektur, data binding berfungsi lancar dengan objek ViewModel. Anda dapat menggunakan StateFlow dan ViewModel bersama-sama sebagai berikut:

class ScheduleViewModel : ViewModel() {

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

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

Di tata letak, tetapkan properti dan metode objek ViewModel ke tampilan yang terkait menggunakan ekspresi binding, seperti yang ditunjukkan pada contoh berikut:

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

UI secara otomatis diupdate setiap kali nilai nama pengguna berubah.

Nonaktifkan dukungan StateFlow

Untuk aplikasi yang menggunakan Kotlin dan AndroidX, dukungan StateFlow otomatis disertakan dengan data binding. Ini berarti bahwa dependensi coroutine otomatis disertakan dalam aplikasi Anda jika dependensi belum tersedia.

Anda dapat memilih untuk tidak menggunakan fungsi ini dengan menambahkan kode berikut ke file build.gradle:

Groovy

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

Kotlin

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

Atau, Anda dapat menonaktifkan StateFlow secara global dalam project dengan menambahkan baris berikut ke file gradle.properties:

Groovy

android.defaults.databinding.addKtx = false

Kotlin

android.defaults.databinding.addKtx = false

Referensi lainnya

Untuk mempelajari data binding lebih lanjut, lihat referensi tambahan berikut ini:

Contoh

Codelab

Postingan blog