概述
DataBinding 是2015谷歌 I/O 大会上介绍的一个数据绑定框架,顾名思义,它可以在数据与视图之间建立一种绑定关系,当数据改变时视图自动更新内容,当视图内容更新时数据自动改变。举个例子,今天晚上你要晚点回家,你要告诉你爸爸和妈妈,在没有 DataBinding 之前,你需要给你爸爸和妈妈分别打个电话,有了 DataBinding 之后,你爸爸和妈妈之间就建立了一种绑定关系,你给其中一个人打电话,他(她)就会通知另一个人知晓,这样就简化了你的操作~
网上很多文章在介绍 DataBinding 时往往会提到它的一个优点:可以省去 findViewById,findViewById 确实看起来冗余重复,写起来毫无营养,于是就有人开始基于注解的方式,在运行时通过反射手段动态查找,比如 xUtils.ViewUtils 框架,但是反射会可观的降低性能。同样是基于注解,把时间消耗转移到编译期,生成查找类的代码,不使用反射,不就可以保留性能了吗?于是有了 Jake 大神的 ButterKnife ,确实很不错,性能和 findViewById 差不多,所以深受 Android 程序员的喜爱,下面是对三者一次不严谨的性能测试:
findViewById: 34851 ns.
ButterKnife:time: 43059 ns
xUtils.ViewUtils: 5015032 ns
可以看到 ButterKnife 的性能消耗几乎可以忽略,如果非要说它的缺点的话,那就是会生成代码,增加方法数。最后就是我们的主角 DataBinding 了,同样是编译期生成代码,但不是基于注解,而是用数据绑定的方式将变量引入布局,当你用熟了它之后,你会发现在代码中操作控件的机会比之前减少很多很多,因为对控件的操作都转移成对数据的操作了。而且重点是性能感人,超越了 findViewById ! findViewById 本质上是一次对 VIEW 树的遍历查找,每次调用查找控件都会查找一次,虽然是 O(n) 的性能,但多次调用就变成了 O(n) x m。但 DataBinding 则不然,通过一次遍历把所有的控件查找出来,然后赋值给对应的变量,完全不依赖 findViewById,在任何情况下,复杂度都是 O(n) 。同样的是生成代码,但数据绑定框架提供了更多的功能,提高工作效率和性能!这简直让人爱不释手。
Google 说:世界上已经31个 findViewById 的插件了,不过 Google 推出了最后一个那就是 DataBinding。数据绑定的主创甚至说了:我们发布得太晚了,这个东西应该在7,8年前我们发布 Android 的时候就推出的。所以,还在犹豫什么呢?快在你的项目中使用起来吧!
使用
上例中有一个 TextView 和 一个 EditText,他们与同一 data 建立了绑定关系,当改变 EditText 内容时,data 自动改变,而 TextView 也与此 data 有绑定关系,所以 TextView 内容随之更新,下面我们通过代码实现这个效果:
1.启用 DataBinding
在 gradle 的 android 节点下添加:
dataBinding {
enabled = true
}
2.创建 viewModel
public class Person extends BaseObservable{
private String name;
@Bindable
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
}
在你想要绑定的属性的 get 方法上添加 @Bindable 注解,DataBinding 就会自动在 BR 类中生成该属性, notifyPropertyChanged 的作用就是更新与此属性绑定的控件。
3.创建 layout 布局
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="person"
type="com.yhao.test.Person"/>
</data>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="data --> view"
android:text="@{person.name}"
/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:hint="view --> data"
android:text="@={person.name}"/>
</LinearLayout>
</layout>
启用 DataBinding 后,DataBinding 的专用标签 layout、data 等就可以使用了,variable 标签用于声明要绑定的数据,@{person.name} 表示建立 data --> view 单向绑定关系,@={person.name} 表示建立 data <–> view 双向绑定关系。
4.建立绑定关系
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
Person person = new Person();
binding.setPerson(person);
}
}
当布局文件中添加 layout 标签后,Databinding 就会自动生成与布局文件名对应的类,如 ActivityMainBinding 类,然后与 viewModel 实例绑定,就大功告成了。
最后总结一下 DataBinding 的使用步骤:
- 启用 DataBinding
- 创建 viewModel
- 创建 layout 布局
- 建立绑定关系
怎么样,是不是非常简单呢?然而这只是对文本类型数据进行绑定,在实际开发中会有各种各样的数据类型,比如控件的颜色、图片等,将在下篇文章展开~