双向数据绑定

使用单向数据绑定,您可以在属性上设置值, 对该属性的变化做出响应的监听器:

<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 注解,如 以下代码段:

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

由于可绑定属性的 getter 方法称为 getRememberMe(),因此 属性对应的 setter 方法会自动使用 setRememberMe()

如需详细了解如何使用 BaseObservable@Bindable,请参阅使用 可观察的数据对象

使用自定义特性的双向数据绑定

平台为最常见的 双向属性并更改监听器,您可以使用 作为应用的一部分如果您想将双向数据绑定与自定义 属性,则需要使用 @InverseBindingAdapter@InverseBindingMethod 注释。

例如,如果要对 "time" 属性启用双向数据绑定 在名为 MyView 的自定义视图中,完成以下步骤:

  1. 为用于设置初始值并在值更新时更新的方法添加注解 使用 @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. 使用以下代码对从视图中读取值的方法进行注释 @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(); }

此时,数据绑定知道在数据发生更改时要执行什么操作(它会调用 方法,并使用 @BindingAdapter)以及应对措施 在视图属性更改时调用(它会调用 InverseBindingListener)。 但是,它不知道属性何时以及如何发生变化。

为此,您需要在视图上设置监听器。可以是自定义监听器 也可能是一般性事件,如损失 或者文字转换向该方法添加 @BindingAdapter 注解 为属性的更改设置监听器:

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

该监听器包含一个 InverseBindingListener 参数。您可以使用 InverseBindingListener,用于告知数据绑定系统该属性已 已更改。然后,系统可以开始调用使用 @InverseBindingAdapter 等。

实际上,此监听器包含一些重要逻辑,包括监听器 实现单向数据绑定如需查看示例,请参阅文本属性的适配器 更改, TextViewBindingAdapter

转化者数量

如果绑定到 View 对象的变量 需要进行格式设置、翻译或进行更改后才能展示 您可以使用 Converter 对象。

以显示日期的 EditText 对象为例:

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

viewmodel.birthDate 属性包含 Long 类型的值,因此需要 转换数据。

由于使用了双向表达式,因此还需要使用反向表达式 conversioner,用于告知库如何将用户提供的字符串转换回 后备数据类型,在本例中为 Long。这个过程是通过将 @InverseMethod 注解 传递给其中一个转换器,并让这个注解引用反向的 转换器。以下代码中显示了此配置的示例 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.  } }

使用双向数据绑定的无限循环

使用双向数据绑定时,请注意不要引入无限循环。时间 当用户更改某个属性时,使用 调用 @InverseBindingAdapter,并将值分配给后备 属性。进而调用使用 @BindingAdapter,这会再次调用带注解的方法 使用 @InverseBindingAdapter,依此类推。

因此,请务必通过比较 使用 @BindingAdapter 注解的方法中的新值和旧值。

双向特性

当您使用 API 时,该平台内置了对双向数据绑定的支持。 下表中的属性。如需详细了解该平台如何提供 请参阅相应绑定适配器的实现:

特性 绑定适配器
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

其他资源

如需详细了解数据绑定,请参阅以下资源: 其他资源

示例

Codelab

博文