2015年的GoogleI/O大会上,Google推出了自己官方的数据绑定框架Data Binding Library,虽然网络上有很多第三方的数据绑定框架,但是,第三方的框架都是别的公司或者团队在维护,有些公司或者团队看到自己的东西没有很好的收益或者其他原因,一下子就不在维护了,这对我们来说就是一个大麻烦,所以,使用官方的框架是我们第一个选择。
在没有出来这个以前,我们获取控件的句柄一般是通过findViewById或者使用注解,使用注解虽然是不需要我们写很多的findViewById,但是大量使用注解会拖慢我们APP的速度。但是使用Data Binding就不会,根据官方文档的解析,使用Data Binding还会提高XML的解析速度。Data Binding的推出,解决了Android UI编程的一个痛点,是Google官方对MVVM在Android上的一个实现,我们可以在不改变原有框架的基础上,使用这些新特性。使用Data Binding可以让我们开发中减少很多与UI相关的代码,可以直接将数据绑定到XML上,可以实现自动刷新。
下面开始使用这个官方的大杀器
1、开发环境
将Android studio更新到最新版本,现在Google也在我大天朝上线了开发者网站,我们不在需要跨过长城了,下面提供一下Google在天朝的开发者网站地址:https://developer.android.google.cn/index.html
更新完Android studio之后,将Gradle也更新到新的版本,最少不低于1.5.0版本,我用的是最新的2.2.3版本:
classpath 'com.android.tools.build:gradle:2.2.3'
然后在当前model的android{}闭包中添加对Data Binding的支持:
android {
...
dataBinding {
enabled true
}
}
这样准备好了环境,下面开始一个简单的例子
2、Data Binding简单例子
在上面的环境准备好了之后,我们可以开始编写代码:
首先,我们需要一个普通的JavaBean,一个简单的Student类:
public class Student {
private String name;
private String addr;
public Student() {
}
public Student(String name, String addr) {
this.name = name;
this.addr = addr;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddr() {
return this.addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
}
这是一个简单的JavaBean,提供相应的get和set方法。
接着是布局文件的编码:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.databindingdemo.Student"/>
<variable
name="stu"
type="Student"/>
</data>
<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.databindingdemo.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{stu.name}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{stu.addr}"/>
</LinearLayout>
</layout>
需要注意的是,根布局不再是以前ViewGroup,而是一个Layout,里面的命名空间不能重复,比如有android的约束就不能在ViewGroup的根节点中重复使用,否则编译不过去的。
完成布局代码之后,就是Activity的编码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding a = DataBindingUtil.setContentView(this, R.layout.activity_main);
a.setStu(new Student("Devin", "广州"));
}
}
这样就可以实现在我们布局中显示数据,最后的结果是:
这样我们就可以很简单地实现了一个Data Binding的例子。这样在Activity中我们就不需要写很多的代码,activity里面也变得非常简洁明了。
3、Data Binding入门
上面我们简单实现了Data Binding,下面我们详细地了解一下。
首先从布局文件入手,先看一下布局文件:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.databindingdemo.Student"/>
<variable
name="stu"
type="Student"/>
</data>
<LinearLayout
...
</LinearLayout>
</layout>
布局文件中,根节点不再是ViewGroup,而是layout,layout下面有两个节点,分别是<data>和<LinearLayout>,LinearLayout是一个ViewGroup,ViewGroup里面写我们具体的布局代码,data里面就是我们绑定的数据,下面解析一下data这个节点。
<data>
<import type="com.databindingdemo.Student"/>
<variable
name="stu"
type="Student"/>
</data>
data节点里面有两个节点,分别是import和variable,import就是引入JavaBean对象,type的值就是全限定类名。我们可以引入多个类,当引入的类同名的时候,我们还可以在import中添加一个类的别名,例如:
<import type="com.example.home.data.User" />
<import type="com.examle.detail.data.User" alias="DetailUser" />
<variable name="user" type="DetailUser" />
这里引入的类名字都是User,我们可以用alias这个属性起一个别名,用于区分不同的类,这是import标签,下面了解一下variable标签。
其中variable就是我们用来定义变量的,在上面的例子中我们就定义了一个stu变量,类型就是一个JavaBean,我们还可以定义List、Map、String等的变量,例如:
<variable
name="list"
type="ArrayList<String>" />
<variable
name="map"
type="HashMap<String, String>" />
等等,然后我们就可以在布局文件中使用这些定义的变量,这个就是variable标签的基本作用。
这里就是布局文件的基本解析,下面了解一下Activity里面的代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding mainBinding = DataBindingUtil.setContentView(this,
R.layout.activity_main);
mainBinding.setStu(new Student("Devin", "广州"));
}
这里的代码非常简单,就两句代码。下面我们了解一下
DataBindingUtil是layout创建数据绑定类,当我们使用这个类并调用setContentView()方法的时候,会创建一个ActivityMainBinding对象,这个ActivityMainBinding是Data Binding自动生成的,根据布局文件命名,比如我们这里的布局文件名是:activity_main,然后生成的就是ActivityMainBinding,这个类的基类是ViewDataBinding,然后调用set方法将数据注入进去,最后就可以实现数据的展示。
ActivityMainBinding这个类是自动生成,生成的规则是:
布局文件名首字母大写,去掉下划线,下划线后面首字母大写,加上Binding
除了可以这样直接生成之外,Google还给我提供了自定义Binding类名的方法,就是在data中加一个class字段就可以了。
4、Data Binding其他使用
绑定事件
我们通常给Button设置点击事件都是通过注解绑定或者setOnClickListener,Data Binding也给我提供了可以绑定事件的方法,下面我们具体实现一下。
首先是布局文件的代码:
<data>
<import type="com.databindingdemo.Student"/>
<import type="com.databindingdemo.OnClickListener"/>
<variable
name="stu"
type="Student"/>
<variable
name="click"
type="OnClickListener"/>
</data>
需要定义一个OnClickListener类,这里面是我们的点击事件:
public class OnClickListener {
public void onClick(View view) {
Toast.makeText(view.getContext(), "绑定了点击事件", Toast.LENGTH_LONG).show();
}
}
然后在布局文件中使用:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{click.onClick}"
android:text="绑定点击事件"/>
最后在activity中做一个设置:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding mainBinding = DataBindingUtil.setContentView(this,
R.layout.activity_main);
mainBinding.setStu(new Student("Devin", "广州"));
mainBinding.setClick(new OnClickListener());
}
这样就可以实现点击事件。
表达式
Data Binding也支持使用表达式,下面是Data Binding的常用表达式跟JAVA的表达式差不多
- 数学计算 + / * %
- 字符串连接 +
- 逻辑 && ||
- 二进制 & | ^
- 一元 + ! ~
- 位移 >> >>> <<
- 比较 == > < >= <=
- instanceof
- 组 ()
- 字面量 字符,字符串,数字, null
- 类型转换
- 函数调用
- 字段存取
- 数组存取 []
- 三元运算符 ?:
有一个特殊的就是null合并,例如:
android:text='@{str==null ?? "not null"}'
解析一下:str是否是null,是null的话text的值就是str,否则就是not null里面的值,类似与三目运算符。
数据刷新
Data Binding给我们提供了内容观察者去刷新数据的改变,这个跟我们在RecyclerView中设置Adapter通过调用notifyDatasetChanged()方法通知UI刷新数据一样。Google官方给我们提供了非常简单的一种方式去实现,下面我们了解一下具体的步骤:
JavaBean继承BaseObservable这个类
在Getter方法上面添加@Bindable注解
在Setter方法中调用notifyPropertyChanged(BR.name);
这样就可以完成了,是不是很简单。我们会发现,在notifyPropertyChanged()方法中有一个参数,BR,那么BR是什么呢?BR跟R差不多,保存我们变量的引用地址。
上面就是Data Binding的基本解析,当然还有其它很多的高级用法,欢迎大家留言交流!!!!