转载

Data Binding

Data BindingAndroid 待发布的支持库,它可以将逻辑和代码关联起来,避免开发者书写大量的胶合代码。

此前,布局文件XML被认为是相对静态的,往往需要在Java代码中处理与其有关的逻辑;数据绑定技术( Data Binding )改造了布局文件使其能够导入Java类,定义和使用变量,具备像Java代码一样的灵活性,从而使得XML文件变的更加动态化,支持更强大的功能。

添加依赖

在项目顶层的 gradle 中添加依赖

dependencies {     classpath "com.android.tools.build:gradle:1.2.3"     classpath "com.android.databinding:dataBinder:1.0-rc0" }

在具体模块 gradle 配置文件中启用该插件

apply plugin: 'com.android.databinding'

使用示例

现在有一个 User

public class User {  public final String firstName;  public final String lastName;  public User(String firstName, String lastName) {    this.firstName = firstName;    this.lastName = lastName;  } } 

考虑一个专门用来显示 User全名TextView ,使用数据绑定可以在 layout 布局文件中就指定其显示的内容为 User 对象的全名。这个布局文件 databinding_layout.xml 如下

//1.根标签为 layout <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android">  //2.data标签定义所使用数据域对象  <data>   //3.variable标签根据Java类建立变量   <variable    name="user" //声明变量名称    type="com.example.migratingtest.User" //指定变量类型   />  </data>  //4.静态布局  <LinearLayout   android:layout_width="match_parent"   android:layout_height="match_parent"   android:orientation="vertical">   <TextView    android:layout_margin="20dp"    android:padding="20dp"    android:background="#55ffff00"    //5.用@{user.firstName}格式使用定义的类对象user    android:text="@{user.firstName}+@{user.getLastName()}"    android:layout_width="match_parent"    android:layout_height="match_parent" />  </LinearLayout> </layout> 

布局文件中定义了对象 usertextview 的对应关系,但要传入的对象 user 还需要在Java代码中生成;同时这个布局文件将按名称生成一个 DatabindingLayoutBinding 类,位于 app/build/intermediates/classes/debug/<包名>/databinding 目录下,需要在Java代码中作为布局载入;而后将二者绑定起来。

//1.载入新布局类 DatabindingLayoutBinding binding = DataBindingUtil.setContentView(this, R.layout.databinding_layout); //2.产生User对象 User user = new User("liu", "xiangtian"); //3.绑定布局和具体对象 binding.setUser(user);

更多用法

布局文件中 data 可以像Java代码一样导入类,并直接使用其类静态变量/方法,使用 variable 标签声明和建立对象;

类和对象的域/方法均可以在布局文件中使用,也支持相关运算,如上例中的字符连接符 +

观察者模式

上述仅是数据绑定的基本功能,如果 User 对象一被改变,布局界面就自动更新, 数据绑定 才显得名副其实。其实现很容易让人联想到观察者模式, User 对象继承 Observable 作为被观察者,但问题是这种实现更新需要主动使用 notify 函数来通知观察者们;为此, android 使用 BaseObservable 类和 Bindable 注解实现自动通知。

要改的仅仅是 User 类。

//1.继承BaseObservable类成为被观察者 public class User extends BaseObservable{  public String firstName;  //2.给get方法Bindable注解  @Bindable  public String getFirstName() {   return firstName;  }  //3.给set方法添加`notify`方法  public void setLastName(String lastName) {   this.lastName = lastName;   notifyPropertyChanged(BR.lastName);  } } 

BR 亦是编译时生成类,同样位于 app/build/intermediates/classes/debug/<包名>/ 目录下,其内容是:

public class BR {     public static final int _all = 0;     public static final int firstName = 1;     public static final int lastName = 2;     public static final int user = 3; }

此后当使用 user.setFirstName("li") 更改数据后,布局中将相应变化。

BR 代码可知, User 类中所有域均被编入被观察者列表中,这有时并不合理。为了灵活起见,可以使用 ObservableFields 单独对某个引用域进行转换,使用 ObservableInt 等对基本类型进行转换。

依然改 User

public class User {     public ObservableField<String> firstName = new ObservableField<>();     public ObservableField<String> lastName = new ObservableField<>(); }

在Java代码中初始化 User

User user = new User(); //ObservableField是一个包装类,提供get/set方法处理包装的内容对象 user.firstName.set("liu"); user.lastName.set("xiangtian");

布局文件仍然使用 @{user.firstName} 即可,不需要使用 @{user.firstName.get}

绑定关系类

生成的新布局文件是一个代表绑定关系的类 DatabindingLayoutBinding ,这个类继承自 ViewDataBinding ,其中包含所有在布局中声明了的类对象 和 参与绑定的全部 View ,并提供了相应了 set/get 方法以及解除所有绑定的 unbind 方法。如示例中

// views private final android.widget.LinearLayout mboundView0; private final android.widget.TextView mboundView1; // variables private com.example.migratingtest.User mUser; 
正文到此结束
Loading...