Android 团队发布了一个 数据绑定框架(Data Binding Library) 。以后可以直接在 layout 布局 xml 文件中绑定数据了,无需再 findViewById 然后手工设置数据了。其语法和使用方式和 JSP 中的 EL 表达式非常类似。
Data Binding Library 是一个 support 库,支持 Android 2.1+ 版本 (API level 7+)。 由于该框架需要使用编译器来生成很多代码,所以需要配合最新版本的 Android Studio (1.3.0-beta1 + 版本)才能使用。
另外需要注意的是,Data Binding Library 还处于 beta 测试阶段,所以 API 还不稳定,随时可能会修改 API 接口,同时还有很多 BUG, 如果您使用过程中遇到了 bug ,可以到这里反馈: https://code.google.com/p/android-developer-preview/ 。
官方介绍中有一条明确指出android gradle版本必须大于1.5.0-alpha:
To use data binding, Android Plugin for Gradle 1.5.0-alpha1 or higher is required.
最新版的 Android Studio 已经内置了对 Android Data Binding 框架的支持,配置起来也很简单,只需要在 app 的 build.gradle 文件中添加下面的内容就好了
android {
....
dataBinding {
enabled = true
}
}
配置完成之后,等项目构建完成,你会发现项目External Libraries中多了四个aar包:
adapters-1.0-rc3 定义了一些DataBinding的组件
baseLibrary-1.0-rc5 定义了一些DataBinding的annotation和回调接口
compiler-1.0-rc5 定义了一些用于编译DataBinding的工具类
library-1.0-rc3 定义了一些Observable基本类型
四个jar包加起来总共也不会超过200KB。
使用
使用DataBinding库将会改变android传统开发流程中Layout文件的编写方式,这就是ViewModel的核心,将视图和Model绑定在一起,你只需要修改Model层的值,对应的View层就会监听到自动修改自身。
Data Binding Layout文件
android 的res/layout文件下放着应用的全部界面视图,Data Binding Layout文件也是放在该目录下,其实就是修改传统layout文件就可以让它变成一个Data Binding Layout文件。
Data Binding layout 文件有点不同的是:起始根标签是 layout,接下来一个 data 元素以及一个 view 的根元素。这个 view 元素就是你没有使用 Data Binding的layout文件的根元素。举例说明如下:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"/>
</LinearLayout>
</layout>
在data内描述了一个名为user的变量属性,使其可以在这个layout中使用:
<variable name="user" type="com.example.User"/>
在layout的属性表达式写作 @{},下面是一个 TextView 的 text 设置为 user 的 firstName 属性:
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"/>
请注意这个layout的文件名,DataBinding会根据这个layout的文件名生成一个xxBinding类,这个类继承自ViewDataBiding;如果layout文件名是content_main.xml,则会生成一个ContentMainBinding类,根据官方解释是自动把layout文件名的下滑线去掉,然后采用驼峰式的命名规则,然后再加上Binding后缀。这也说明了android里的layout编译器会把其转换成一个单独的类,每个layout对应一个layout的类。只不过用DataBinding库把这个layout类转换重新实现过。
Data Object
假设你有一个user的plain-old Java Object(POJO):
public class User {
public final String firstName;
public final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
这个类型的对象拥有从不改变的数据。在 app 中它是常见的,可以读取一次并且之后从不改变。当然也可以使用 JavaBeans 对象:
public class User {
private final String firstName;
private final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
}
从 Data Binding 的角度来看,这两个类是等价的。用于 TextView 中的 android:text 属性的表达式 @{user.firstName} 将访问前者 POJO 对象中的 firstName 和后者 JavaBeans 对象中的 getFirstName() 方法。
绑定数据
public class MainFragment extends Fragment {private ContentMainBinding mMainBinding; private UserModel mUserModel; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.content_main, container, false); // 方式1,直接用默认生成的Binding类绑定 mMainBinding = ContentMainBinding.bind(view); // 方式2,向上转成ViewDataBinding类型 // ViewDataBinding viewDataBinding = ContentMainBinding.bind(view); // mMainBinding = (ContentMainBinding) viewDataBinding; //方式3,使用生成的Binding的inflater, // mMainBinding = ContentMainBinding.inflate(inflater); //方式4,使用生成的Binding的inflater,类似Inflater api // mMainBinding = ContentMainBinding.inflate(inflater, container, false); //方式5,某种情况无法生存默认Binding的情况下,并且把对应的layout传入 // ViewDataBinding viewDataBinding = DataBindingUtil.inflate(inflater, R.layout.content_main, container, false); // mMainBinding = (ContentMainBinding) viewDataBinding; //方式6,某种情况无法生存默认Binding的情况下 // ViewDataBinding viewDataBinding = DataBindingUtil.bind(view); mUserModel = new UserModel(this, getResources()); mMainBinding.setUser(mUserModel); attachButtonListener(); return view; }
如果是在Activity中使用方式是:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
User user = new User("Test", "User");
binding.setUser(user);
}
步骤一:初始化对应layout的Binding类;
步骤二:初始化对应layout的Model类;
步骤三:将对应layout的Model类和Binding类进行绑定;
这里用到了上面layout默认自动生成的Binding类,有很多种不同的API可以初始化Binding类,不同方法在根据不同情况具体调用。
Model类和Binding类的绑定api依赖于data binding layout的配置。这里配置的是:
<variable name="user" type="com.example.User"/>
即variable name=”user” 这里的name属性是user,对应Binding类的setUser方法,这个方法也是默认自动生成的,采用驼峰式。
然后你就可以通过修改UserModel的值达到自动修改View的效果了。
上面演示了最简单的Data Binding库的使用,更深入更高级的使用官方文档已经向我们介绍了。不过要习惯这种模式的开发,还需要一段时间的使用来适应它。
参考资料:http://developer.android.com/intl/zh-cn/tools/data-binding/guide.html
https://realm.io/cn/news/data-binding-android-boyar-mount/?utm_source=tuicool&utm_medium=referral
http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0603/2992.html