Observing data(Model)
任何 POJO 对象都能用在 Data Binding 中,但是更改 POJO 并不会同步更新 UI。Data Binding 的强大之处就在于它可以让你的数据拥有更新通知的能力。
有三种不同的动态更新数据的机制:
- Observable 对象
- Observable 字段
- Observable 容器类
Observable 对象
当一个类实现了Observable
接口时,Data Binding 会设置一个 listener
在绑定的对象上,以便监听对象属性的变动。
Observable
接口有一个添加/移除 listener
的机制。为了简化开发,Data Binding提供了BaseObservable类,这个类也实现了属性变动的通知,只需要在 getter 上使用 @Bindable
注解,并在 setter 中添加 notifyPropertyChanged()
方法,如下:
public class Book extends BaseObservable {
private String name;
private Integer price;
@Bindable
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.price);
}
@Bindable
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
notifyPropertyChanged(BR.name);
}
}
注:Data Binding 会生成一个BR类,该类包含用于数据绑定的资源的id
Observable Fields
如果pojo类属性很少的话,可以使用 ObservableField
以及它的子类:
- ObservableBoolean
- ObservableByte
- ObservableChar
- ObservableShort
- ObservableInt
- ObservableLong
- ObservableFloat
- ObservableDouble
- ObservableParcelable
ObservableFields 是包含 observable 对象的单一字段。原始版本避免了在存取过程中做打包/解包操作,pojo的属性要使用 public final修饰,如下:
public class Book {
public final ObservableField name = new ObservableField<>();
public final ObservableInt price = new ObservableInt();
public Book(String name, Integer price) {
this.name.set(name);
this.price.set(price);
}
}
要存取数据,只需要使用 get() / set() 方法:
book.price.set(10);
book.price.get();
Observable 容器类
Observable 容器类允许使用 key-value
形式存储数据。当 key 是类似 String 的一类引用类型时,使用 ObservableArrayMap 会非常方便,如下:
ObservableArrayMap book = new ObservableArrayMap<>();
book.put("name", "Think in JAVA");
book.put("price", 12);
binding.setBook(book);
...
注:<
符号要写成<
DataBinding绑定类
Data Binding的绑定类,用于访问布局的数据和视图,关联View和数据,绑定类的名称和包都可以在布局文件中自定义。如下:
...
所有生成的绑定类都继承自ViewDataBinding类。
创建绑定对象
binding 应该在 inflate 之后创建,确保 View 的层次结构不会在绑定前被干扰,如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
}
使用Data Binding 提供的工具类更简单如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
}
如果在Fragment,ListView或RecyclerView Adapter中使用数据绑定,可以使用DataBindingUtil.inflate()
方法,如下:
ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
// or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
id视图
布局中每一个带有 id 的 View,都会生成一个 public final 的属性。如下:
TextView textView = binding.name;
双向数据绑定
双向数据绑定Data Binding 提供一个非常简单的方式
@={}
表示接收属性的数据更改并同时监听数据的更新,实现双向绑定
注:双向绑定仅支持部分的组件的属性
支持列表
- demo
- DataBinding 入门