Two-way data binding (雙向數據綁定)

前言


使用單向數據綁定可以在屬性上設置數值,並可設定對該屬性的變化作出反應的監聽器。如下
<CheckBox  
android:id="@+id/rememberMeCheckBox"
android:checked="@{viewmodel.rememberMe}"
android:onCheckedChanged="@{viewmodel.rememberMeChanged}"
/>

雙向數據綁定提供了此過程的捷徑。如下
<CheckBox  
android:id="@+id/rememberMeCheckBox"
android:checked="@={viewmodel.rememberMe}"
/>

注意在 @={} 表示法中的 = 符號表示了同時接受資料變化以及監聽更新。

為了對數據的變化做出反應,可以讓佈局變量成為 Observable 的實現,通常是 BaseObservable,並使用 @Bindable 註釋,如下
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);
}
}
}

由於 bindable 屬性的 getter 方法稱為 getRememberMe(),因此屬性的相應 setter 方法會自動使用名稱 setRememberMe()。

關於使用 BaseObservable 和 @Bindable 的更多訊息,參考 Work with observable data objects.

Two-way data binding using custom attributes


該平台為最常見的雙向屬性和監聽器提供雙向數據綁定的實現,使用者可以將當作應用程序的一部分。

若使用者想在自定義屬性上使用雙向資料綁定則必須了解如何使用 @InverseBindingAdapter 和 @InverseBindingMethod 註解。

例如,如果要在名稱為 MyView 的自定義視圖中對 "time" 屬性啟用雙向數據綁定,必須完成以下步驟

1.註釋設置初始值的方法,並在使用 @BindingAdapter 更改時進行更新
@BindingAdapter("time")  
public static void setTime(MyView view, Time newValue) {
// Important to break potential infinite loops.
if (view.time != newValue) {
view.time = newValue;
}
}

2.使用 @InverseBindingAdapter 註釋從視圖中讀取數值的方法
@InverseBindingAdapter("time")  
public static Time getTime(MyView view) {
return view.getTime();
}

此時,data binding library 知道數據變化時要執行的操作(呼叫使用 @BindingAdapter 註釋的方法)以及視圖屬性變化時調用的內容(它呼叫 InverseBindingListener)。

為此,需要在視圖上設置一個監聽器。它可以是與自定義視圖關聯的自定義監聽器,也可以是通用事件,例如失去焦點或文本更改。

將 @BindingAdapter 註釋添加到為該屬性的變化設置監聽器的方法,如下
@BindingAdapter("app:timeAttrChanged")  
public static void setListeners(
MyView view, final InverseBindingListener attrChange) {
// Set a listener for click, focus, touch, etc.
}

這個 Listener 包含了 InverseBindingListener 作為參數,可以使用 InverseBindingListener 告知 data binding library 該屬性已更改。接著,系統可以開始使用 @InverseBindingAdapter 呼叫註釋方法,依此類推。

注意每個雙向綁定都會生成一個合成事件屬性( synthetic event attribute)。此屬性與基本屬性具有相同的名稱,但具有後綴 "AttrChanged"。

合成事件屬性允許 data binding library 建立使用 @BindingAdapter 註釋的方法,以將事件監聽器連結到 View 的相應實體。

在實作中,該監聽器包括一些特殊的邏輯,包括用於單向數據綁定的監聽器。相關範例,參考TextViewBindingAdapter

 

Converters


如果綁定到 View 對象的變數需要在顯示之前進行格式化,轉換或更改,則可以使用 Converter 對象。

例如,使用顯示日期的 EditText 對象
<EditText  
android:id="@+id/birth_date"
android:text="@={Converter.dateToString(viewmodel.birthDate)}"
/>

viewmodel.birthDate 屬性包含 Long 類型的值,因此需要使用轉換器對其進行格式化。

因為使用雙向表達式,所以還需要一個反向轉換器(inverse converter)讓 data binding library 知道如何將字符串轉換回數據類型,在本例中為 Long。

此過程通過將 @InverseMethod 註釋添加到其中一個轉換器並使此註釋引用反向轉換器來完成。如下
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.
}
}

 

Infinite loops using two-way data binding


使用雙向數據綁定時,小心不要引入無限迴圈。

當用戶更改屬性時,將呼叫使用 @InverseBindingAdapter 註釋的方法,並將數值分配給 屬性。反過來,這將呼叫使用 @BindingAdapter 註釋的方法,這將觸發對使用 @InverseBindingAdapter 註釋的方法的另一個調用,依此類推。

因此,通過比較使用 @BindingAdapter 註釋的方法中的新値和舊值來打破可能的無限循環非常重要。

 

Two-way attributes


下表為平台預設的雙向綁定屬性表。














Class
Attribute(s)
Binding adapter

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




Orignal From: Two-way data binding (雙向數據綁定)

0 意見:

張貼留言

Twitter Delicious Facebook Digg Stumbleupon Favorites More

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Affiliate Network Reviews