android 双向数据绑定,双向数据绑定  |  Android 开发者  |  Android Developers

使用单向数据绑定时,您可以为特性设置值,并设置对该特性的变化作出反应的监听器:

android:id="@+id/rememberMeCheckBox"

android:checked="@{viewmodel.rememberMe}"

android:onCheckedChanged="@{viewmodel.rememberMeChanged}"

/>

双向数据绑定为此过程提供了一种快捷方式:

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 注释。

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

使用 @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;

}

}

使用 @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 注释的方法)以及当 view 视特性发生更改时要调用的内容(调用 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 注释的方法,依此类推。

注意:每个双向绑定都会生成“合成事件特性”。该特性与基本特性具有相同的名称,但包含后缀 "AttrChanged"。合成事件特性允许库创建使用 @BindingAdapter 注释的方法,以将事件监听器与相应的 View 实例相关联。

实际上,此监听器包含一些复杂逻辑,包括用于单向数据绑定的监听器。用于文本属性更改的适配器 TextViewBindingAdapter 就是一个例子。

转换器

如果绑定到 View 对象的变量需要设置格式、转换或更改后才能显示,则可以使用 Converter 对象。

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

android:id="@+id/birth_date"

android:text="@={Converter.dateToString(viewmodel.birthDate)}"

/>

viewmodel.birthDate 属性包含 Long 类型的值,因此需要使用转换器设置格式。

由于使用了双向表达式,因此还需要使用反向转换器,以告知库如何将用户提供的字符串转换回后备数据类型(在本例中为 Long)。此过程是通过向其中一个转换器添加 @InverseMethod 注释并让此注释引用反向转换器来完成的。以下代码段显示了此配置的一个示例:

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 注释的方法中的新值和旧值,可以打破可能出现的无限循环。

双向特性

当您使用下表中的特性时,该平台提供对双向数据绑定的内置支持。有关平台如何提供此类支持的详细信息,请参阅相应绑定适配器的实现:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值