Bekerja dengan objek data yang dapat diamati

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

Anda dapat menggunakan objek apa pun untuk data binding, tetapi memodifikasi objek tidak dapat secara otomatis menyebabkan UI diperbarui. Anda dapat menggunakan {i>data binding<i} untuk memberikan kemampuan untuk memberi tahu objek lain—yang dikenal sebagai pemroses—saat perubahan data mereka. Ada tiga jenis class yang dapat diobservasi: kolom, koleksi, dan objek.

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

Kolom yang dapat diobservasi

Jika class Anda hanya memiliki beberapa properti, mungkin tidak akan sepadan dengan upaya untuk membuat class yang menerapkan Antarmuka Observable. Di sini ini, Anda dapat menggunakan class Observable generik dan class class khusus primitif agar kolom dapat diamati:

Kolom yang dapat diobservasi adalah objek mandiri yang dapat diamati dengan satu kolom tersebut. Versi primitif menghindari boxing dan unboxing selama akses operasional bisnis. Untuk menggunakan mekanisme ini, buat properti public final di Java atau properti hanya baca di Kotlin, seperti yang ditampilkan 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 set() dan Metode pengakses get() atau gunakan properti Kotlin sintaksis:

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 dengan menggunakan sebuah kunci. Tujuan Class ObservableArrayMap berguna jika kunci adalah jenis referensi, seperti String, seperti yang ditampilkan 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 ditampilkan dalam 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"/>

ObservableArrayList akan berguna jika kunci berupa 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 mengimplementasikan antarmuka Observable memungkinkan pendaftaran pemroses yang ingin diberi tahu tentang perubahan properti dari observable .

Antarmuka Observable memiliki mekanisme untuk menambahkan dan menghapus pemroses, tetapi Anda memutuskan kapan notifikasi dikirim. Untuk mempermudah pengembangan, Data Library Binding menyediakan Class BaseObservable, yang mengimplementasikan mekanisme pendaftaran pemroses. Class data yang mengimplementasikan BaseObservable bertanggung jawab untuk memberi tahu saat properti berubah. Yang akan dilakukan tetapkan anotasi Bindable ke pengambil dan memanggil notifyPropertyChanged() dalam penyetel, seperti yang ditampilkan 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 dengan nama BR dalam paket modul, yang berisi ID dari resource yang digunakan untuk data binding. Anotasi Bindable membuat entri di file class BR selama kompilasi. Jika kelas dasar Jika class data tidak dapat diubah, Anda dapat menerapkan antarmuka Observable menggunakan PropertyChangeRegistry untuk mendaftarkan dan memberi tahu pemroses secara efisien.

Objek berbasis siklus proses

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

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

Menggunakan StateFlow

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

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 Arsitektur Komponen, data binding berfungsi lancar dengan ViewModel objek terstruktur dalam jumlah besar. Anda dapat menggunakan StateFlow dan ViewModel secara bersamaan 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 Anda ke tampilan terkait menggunakan ekspresi binding, seperti ditunjukkan dalam contoh:

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

UI secara otomatis diupdate setiap kali nilai nama pengguna berubah.

Menonaktifkan dukungan StateFlow

Untuk aplikasi yang menggunakan Kotlin dan AndroidX, dukungan StateFlow akan otomatis disertakan dengan data binding. Ini berarti dependensi coroutine disertakan secara otomatis di 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