Android-Data Binding-进阶

2019-07-08  本文已影响0人  quanCN

Observing data(Model)

任何 POJO 对象都能用在 Data Binding 中,但是更改 POJO 并不会同步更新 UI。Data Binding 的强大之处就在于它可以让你的数据拥有更新通知的能力。
有三种不同的动态更新数据的机制:

  1. Observable 对象
  2. Observable 字段
  3. 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 以及它的子类:

ObservableFields 是包含 observable 对象的单一字段。原始版本避免了在存取过程中做打包/解包操作,pojo的属性要使用 public final修饰,如下:

public class Book {
    public final ObservableField<String> 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<String, Object> book = new ObservableArrayMap<>();
book.put("name", "Think in JAVA");
book.put("price", 12);
binding.setBook(book);
<data>
    <import type="android.databinding.ObservableMap"/>
    <variable name="book" type="ObservableMap&lt;String, Object>"/>
</data>
...
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text='@{book["name"]}'/>
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text='@{String.valueOf(book["price"])}'/>

注:<符号要写成&lt;

DataBinding绑定类

Data Binding的绑定类,用于访问布局的数据和视图,关联View和数据,绑定类的名称和包都可以在布局文件中自定义。如下:

<data class="app.mrquan.MyBinding">
...
</data>

所有生成的绑定类都继承自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 的属性。如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <variable name="book" type="app.mrquan.databindingdemo.pojo.Book"/>
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
        <TextView
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text='@{book["name"]}'/>
    </LinearLayout>
</layout>
TextView textView = binding.name;

双向数据绑定

双向数据绑定Data Binding 提供一个非常简单的方式

<EditText
    android:text='@={book.name}'/>

@={} 表示接收属性的数据更改并同时监听数据的更新,实现双向绑定

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <import type="android.databinding.ObservableMap"/>
        <variable name="book" type="ObservableMap&lt;String, String>"/>
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
        <EditText
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text='@={book["name"]}'/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text='@{book["name"]}'/>
    </LinearLayout>
</layout>

注:双向绑定仅支持部分的组件的属性 支持列表

上一篇 下一篇

猜你喜欢

热点阅读