目前為止, 我已經(jīng)向你們展示了如何使用Android Data Binding來更新UI及監(jiān)聽UI事件.但我們也會需要另一件事:將用戶的輸入反饋到程序模塊中. Android2.1引入了"雙向綁定"來實現(xiàn)這個功能.
雙向綁定<a id="orgheadline15"></a>
假設我們有一個表格需要用戶填寫,里面包括了一個EditText用于接受用戶名.單向綁定實現(xiàn)如下:
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"
android:id="@+id/firstName" />
通常,你會讓用戶輸入數(shù)據(jù)然后提交表格. 或者你通過afterTextChanged() 函數(shù)來更新你的模塊. 除了這樣, 你還可以使用雙向綁定操作符 @={} 自動將用戶改變更新到你的view model中.
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@={user.firstName}"/>
由于當用戶輸入時, model就會自動更新, 我再也不用從EditText中捕獲用戶名了.同樣ID也不再需要了.
雙向綁定并不適用于所有屬性, 只支持那些會發(fā)出"改變通知"的屬性. 幸運的是這已經(jīng)包含了大多數(shù)用于輸入相關的屬性. 由于Android Data Binding要最低兼容到API 7,所以沒有新的framework層修改. 否則雙向綁定可以支持所有屬性.
View屬性<a id="orgheadline16"></a>
可以在表達式中訪問View的屬性, 就像訪問數(shù)據(jù)的屬性一樣:
<CheckBox
android:id="@+id/showName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="@{user.firstName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{showName.checked ? View.VISIBLE : View.GONE}"
/>
在上面的配置中, 只有當CheckBox被選中時, 展示用戶名的TextView才可見. 這適用于雙向綁定及所有可以使用data binding表達式的屬性.
<CheckBox
android:id="@+id/showName"
android:focusableInTouchMode="@{model.allowFocusInTouchMode}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="@{user.firstName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusableInTouchMode="@{showName.focusableInTouchMode}"
/>
上面的例子展示了如何使用表達式鏈. 在Data Binding框架內(nèi)部, 當看到"showName.focusableInTouchMode"時,會檢查到它綁定到了"model.allowFocusInTouchMode", 并做簡單的替換.
View引用<a id="orgheadline17"></a>
另一個很酷的事情是, 你可以在lambda表達式中通過View的ID引用他們.
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/firstName"
android:text="@={user.firstName}" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onCheckedChanged="@{()->handler.checked(firstName)}" />