Liên kết dữ liệu hai chiều

Khi sử dụng liên kết dữ liệu một chiều, bạn có thể đặt giá trị cho một thuộc tính và thiết lập trình nghe phản ứng với thay đổi trong thuộc tính đó:

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

Tính năng liên kết dữ liệu hai chiều cung cấp lối tắt đến quy trình này:

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

Ký hiệu @={}, quan trọng là bao gồm cả "=" ký, nhận dữ liệu các thay đổi đối với thuộc tính và đồng thời theo dõi thông tin cập nhật của người dùng.

Để phản ứng với các thay đổi trong dữ liệu sao lưu, bạn có thể tạo bố cục biến một cách triển khai Observable, thường là BaseObservable và sử dụng @Bindable, như minh hoạ trong đoạn mã sau:

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

Vì phương thức getter của thuộc tính có thể liên kết được gọi là getRememberMe(), nên phương thức phương thức setter tương ứng của thuộc tính sẽ tự động sử dụng tên setRememberMe()

Để biết thêm thông tin về cách sử dụng BaseObservable@Bindable, hãy xem bài viết Hợp tác với đối tượng dữ liệu có thể ghi nhận được.

Liên kết dữ liệu hai chiều bằng thuộc tính tuỳ chỉnh

Nền tảng này cung cấp các cách triển khai liên kết dữ liệu hai chiều cho các phương pháp phổ biến nhất thuộc tính hai chiều và thay đổi trình nghe mà bạn có thể dùng như một phần của ứng dụng. Nếu bạn muốn sử dụng liên kết dữ liệu hai chiều bằng bạn cần làm việc với @InverseBindingAdapter@InverseBindingMethod các chú thích.

Ví dụ: nếu bạn muốn bật tính năng liên kết dữ liệu hai chiều trên thuộc tính "time" trong khung hiển thị tuỳ chỉnh có tên là MyView, hãy hoàn tất các bước sau:

  1. Chú thích phương thức đặt giá trị ban đầu và cập nhật khi giá trị đó các thay đổi bằng cách sử dụng @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. Chú giải phương thức đọc giá trị trong khung hiển thị bằng cách sử dụng @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();
    }

Tại thời điểm này, liên kết dữ liệu biết việc cần làm khi dữ liệu thay đổi (nó gọi hàm phương thức được chú thích bằng @BindingAdapter) và những việc cần làm khi thuộc tính khung hiển thị thay đổi (phương thức này gọi phương thức InverseBindingListener). Tuy nhiên, tài sản này không biết thuộc tính này thay đổi khi nào hoặc như thế nào.

Để làm được việc đó, bạn cần thiết lập trình nghe cho thành phần hiển thị (view). Đây có thể là một trình nghe tuỳ chỉnh được liên kết với chế độ xem tuỳ chỉnh hoặc có thể là một sự kiện chung chung, chẳng hạn như mất mát tiêu điểm hoặc thay đổi văn bản. Thêm chú giải @BindingAdapter vào phương thức để thiết lập trình nghe cho các thay đổi trên thuộc tính:

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

Trình nghe này bao gồm InverseBindingListener dưới dạng tham số. Bạn sử dụng InverseBindingListener để cho hệ thống liên kết dữ liệu biết rằng thuộc tính này đã thay đổi. Sau đó, hệ thống có thể bắt đầu gọi phương thức được chú giải bằng cách sử dụng @InverseBindingAdapter, v.v.

Trong thực tế, trình nghe này bao gồm một số logic không quan trọng, bao gồm cả trình nghe để liên kết dữ liệu một chiều. Để biết ví dụ, hãy xem trình chuyển đổi cho thuộc tính văn bản thay đổi, TextViewBindingAdapter.

Người chuyển đổi

Nếu biến được liên kết với đối tượng View cần được định dạng, dịch hoặc thay đổi bằng cách nào đó trước khi được hiển thị, bạn có thể sử dụng đối tượng Converter.

Ví dụ: lấy đối tượng EditText cho thấy ngày:

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

Thuộc tính viewmodel.birthDate chứa giá trị thuộc loại Long nên cần được định dạng bằng trình chuyển đổi.

Vì biểu thức hai chiều đang được sử dụng nên cũng cần phải có nghịch đảo trình chuyển đổi để cho thư viện biết cách chuyển đổi lại chuỗi do người dùng cung cấp kiểu dữ liệu sao lưu, trong trường hợp này là Long. Quá trình này được thực hiện bằng cách thêm chú giải @InverseMethod cho một trong những trình chuyển đổi và có chú thích này tham chiếu giá trị nghịch đảo bộ chuyển đổi. Ví dụ về cấu hình này xuất hiện trong mã sau snippet:

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

Vòng lặp vô hạn sử dụng liên kết dữ liệu hai chiều

Hãy cẩn thận để không tạo vòng lặp vô hạn khi sử dụng liên kết dữ liệu hai chiều. Thời gian người dùng thay đổi một thuộc tính, thì phương thức được chú giải bằng cách sử dụng @InverseBindingAdapter được gọi và giá trị được gán cho phương thức sao lưu thuộc tính này. Đổi lại, thao tác này sẽ gọi phương thức được chú giải bằng cách sử dụng @BindingAdapter, lệnh này sẽ kích hoạt một lệnh gọi khác đến phương thức được chú giải bằng @InverseBindingAdapter, v.v.

Vì lý do này, bạn cần phá vỡ các vòng lặp vô hạn có thể có bằng cách so sánh các giá trị mới và cũ trong các phương thức được chú giải bằng @BindingAdapter.

Thuộc tính hai chiều

Nền tảng này hỗ trợ tích hợp sẵn tính năng liên kết dữ liệu hai chiều khi bạn sử dụng các thuộc tính trong bảng sau. Để biết thông tin chi tiết về cách nền tảng cung cấp hỗ trợ này, hãy xem cách triển khai cho các bộ chuyển đổi liên kết tương ứng:

Lớp (Các) thuộc tính Bộ chuyển đổi liên kết
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

Tài nguyên khác

Để tìm hiểu thêm về liên kết dữ liệu, hãy tham khảo các tài nguyên khác.

Mẫu

Lớp học lập trình

Bài đăng trên blog