Data binding dua arah

Dengan data binding satu arah, Anda dapat menetapkan nilai pada atribut dan menetapkan pemroses yang merespons perubahan pada atribut tersebut:

    <CheckBox
        android:id="@+id/rememberMeCheckBox"
        android:checked="@{viewmodel.rememberMe}"
        android:onCheckedChanged="@{viewmodel.rememberMeChanged}"
    />
    

Data binding dua arah menyediakan pintasan ke proses ini:

    <CheckBox
        android:id="@+id/rememberMeCheckBox"
        android:checked="@={viewmodel.rememberMe}"
    />
    

Notasi @={}, yang mencakup tanda "=", menerima perubahan data pada properti dan secara bersamaan memproses pembaruan pengguna.

Untuk merespons perubahan pada data pendukung, Anda dapat menjadikan variabel tata letak Anda sebagai implementasi Observable, biasanya BaseObservable, dan menggunakan anotasi @Bindable, seperti ditunjukkan dalam cuplikan kode berikut:

Kotlin

    class LoginViewModel : BaseObservable {
        // val data = ...

        @Bindable
        fun getRememberMe(): Boolean {
            return data.rememberMe
        }

        fun setRememberMe(value: Boolean) {
            // Avoids infinite loops.
            if (data.rememberMe != value) {
                data.rememberMe = value

                // React to the change.
                saveData()

                // Notify observers of a new value.
                notifyPropertyChanged(BR.remember_me)
            }
        }
    }
    

Java

    public class LoginViewModel extends BaseObservable {
        // private Model data = ...

        @Bindable
        public Boolean getRememberMe() {
            return data.rememberMe;
        }

        public void setRememberMe(Boolean value) {
            // Avoids infinite loops.
            if (data.rememberMe != value) {
                data.rememberMe = value;

                // React to the change.
                saveData();

                // Notify observers of a new value.
                notifyPropertyChanged(BR.remember_me);
            }
        }
    }

Karena metode pengambil properti bindable ini disebut getRememberMe(), metode penyetel yang terkait untuk properti tersebut akan otomatis menggunakan nama setRememberMe().

Untuk informasi selengkapnya tentang cara menggunakan BaseObservable dan @Bindable, lihat Menggunakan objek data yang dapat diobservasi.

Data binding dua arah menggunakan atribut khusus

Platform ini menyediakan implementasi data binding dua arah untuk atribut dua arah yang paling umum dan mengubah pemroses, yang dapat digunakan sebagai bagian dari aplikasi Anda. Jika ingin menggunakan data binding dua arah dengan atribut khusus, Anda harus menggunakan anotasi @InverseBindingAdapter dan @InverseBindingMethod.

Misalnya, jika ingin mengaktifkan data binding dua arah pada atribut "time" dalam tampilan khusus yang disebut MyView, Anda perlu menyelesaikan langkah-langkah berikut:

  1. Anotasikan metode yang menetapkan nilai awal dan menjalankan pembaruan saat nilai tersebut berubah menggunakan @BindingAdapter:

    Kotlin

        @BindingAdapter("time")
        @JvmStatic fun setTime(view: MyView, newValue: Time) {
            // Important to break potential infinite loops.
            if (view.time != newValue) {
                view.time = newValue
            }
        }

    Java

        @BindingAdapter("time")
        public static void setTime(MyView view, Time newValue) {
            // Important to break potential infinite loops.
            if (view.time != newValue) {
                view.time = newValue;
            }
        }
  2. Anotasikan metode yang membaca nilai ini dari tampilan menggunakan @InverseBindingAdapter:

    Kotlin

        @InverseBindingAdapter("time")
        @JvmStatic fun getTime(view: MyView) : Time {
            return view.getTime()
        }

    Java

        @InverseBindingAdapter("time")
        public static Time getTime(MyView view) {
            return view.getTime();
        }

Pada tahap ini, data binding mengetahui apa yang harus dilakukan saat data berubah (memanggil metode yang dianotasi dengan @BindingAdapter) dan apa yang harus dipanggil saat atribut tampilan berubah (memanggil InverseBindingListener). Namun, data binding tidak mengetahui kapan atau bagaimana atribut ini berubah.

Untuk itu, Anda perlu menetapkan pemroses pada tampilan. Pemroses ini dapat berupa pemroses khusus yang terkait dengan tampilan khusus Anda, atau berupa peristiwa umum, seperti kehilangan fokus atau perubahan teks. Tambahkan anotasi @BindingAdapter ke metode yang menetapkan pemroses untuk perubahan pada properti:

Kotlin

    @BindingAdapter("app:timeAttrChanged")
    @JvmStatic fun setListeners(
            view: MyView,
            attrChange: InverseBindingListener
    ) {
        // Set a listener for click, focus, touch, etc.
    }

Java

    @BindingAdapter("app:timeAttrChanged")
    public static void setListeners(
            MyView view, final InverseBindingListener attrChange) {
        // Set a listener for click, focus, touch, etc.
    }
    

Pemroses ini menyertakan InverseBindingListener sebagai parameter. Gunakan InverseBindingListener untuk memberi tahu sistem data binding bahwa atribut telah berubah. Selanjutnya, sistem dapat mulai memanggil metode yang dianotasi menggunakan @InverseBindingAdapter, dan seterusnya.

Dalam praktiknya, pemroses ini menyertakan logika yang rumit, termasuk pemroses untuk data binding satu arah. Sebagai contoh, lihat adaptor untuk perubahan atribut teks, TextViewBindingAdapter.

Converter

Jika variabel yang terikat ke objek View perlu diformat, diterjemahkan, atau diubah sebelum ditampilkan, objek Converter dapat digunakan.

Misalnya, ambil objek EditText yang menampilkan tanggal:

<EditText
        android:id="@+id/birth_date"
        android:text="@={Converter.dateToString(viewmodel.birthDate)}"
    />
    

Atribut viewmodel.birthDate berisi nilai jenis Long, jadi harus diformat menggunakan converter.

Karena ekspresi dua arah sedang digunakan, perlu ada converter terbalik untuk memberi tahu library cara mengonversi kembali string yang disediakan pengguna menjadi jenis data pendukung, dalam hal ini Long. Proses ini dilakukan dengan menambahkan anotasi @InverseMethod ke salah satu converter dan menyetel anotasi ini agar mereferensikan converter terbalik. Contoh konfigurasi ini terlihat dalam cuplikan kode berikut:

Kotlin

    object Converter {
        @InverseMethod("stringToDate")
        @JvmStatic fun dateToString(
            view: EditText, oldValue: Long,
            value: Long
        ): String {
            // Converts long to String.
        }

        @JvmStatic fun stringToDate(
            view: EditText, oldValue: String,
            value: String
        ): Long {
            // Converts String to long.
        }
    }

Java

    public class Converter {
        @InverseMethod("stringToDate")
        public static String dateToString(EditText view, long oldValue,
                long value) {
            // Converts long to String.
        }

        public static long stringToDate(EditText view, String oldValue,
                String value) {
            // Converts String to long.
        }
    }

Loop tak terbatas menggunakan data binding dua arah

Berhati-hatilah agar tidak menimbulkan loop tak terbatas saat menggunakan data binding dua arah. Saat pengguna mengubah atribut, metode yang dianotasi menggunakan @InverseBindingAdapter akan dipanggil, dan nilainya ditetapkan ke properti pendukung. Akibatnya, metode yang dianotasi menggunakan @BindingAdapter akan dipanggil, yang akan memicu panggilan lainnya ke metode yang dianotasi menggunakan @InverseBindingAdapter, dan seterusnya.

Karena alasan ini, penting untuk memutus kemungkinan loop tak terbatas dengan membandingkan nilai baru dan nilai lama dalam metode yang dianotasi menggunakan @BindingAdapter.

Atribut dua arah

Platform menyediakan dukungan bawaan untuk data binding dua arah saat Anda menggunakan atribut dalam tabel berikut. Untuk detail tentang cara platform memberikan dukungan ini, lihat implementasi untuk adaptor binding yang terkait:

Class Atribut Adaptor binding
AdapterView android:selectedItemPosition
android:selection
AdapterViewBindingAdapter
CalendarView android:date CalendarViewBindingAdapter
CompoundButton android:checked CompoundButtonBindingAdapter
DatePicker android:year
android:month
android:day
DatePickerBindingAdapter
NumberPicker android:value NumberPickerBindingAdapter
RadioButton android:checkedButton RadioGroupBindingAdapter
RatingBar android:rating RatingBarBindingAdapter
SeekBar android:progress SeekBarBindingAdapter
TabHost android:currentTab TabHostBindingAdapter
TextView android:text TextViewBindingAdapter
TimePicker android:hour
android:minute
TimePickerBindingAdapter

Resource lainnya

Untuk mempelajari data binding lebih lanjut, lihat referensi tambahan berikut.

Contoh

Codelab

Postingan blog