DataBinding使用前准备
一、构建环境
只需要在appmoudle下的build.gradle中加入databinding即可:
android {
....
dataBinding {
enabled = true
}
}
*注意android studio版本要在1.5以上
二、databinding的基础用法
1 . 在布局文件中加入databinding如下:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="person" type="com.example.Person"/>
</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="@{person.firstName}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{person.lastName}"/>
</LinearLayout>
</layout>
也就是databinding起始根标签是layout,接下来一个data元素以及一个你没有使用Data Binding的layout文件的根元素。那么这个data元素是干嘛的呢?其实这个data是建立view与viewmoudle之间的桥梁,data中的variable标签又是什么意思呢?其中name就是你给这个variable起的名字,而type就是viewmoudle的全路径包名(该例是com.example包下的Person类);
<variable name="person" type="com.example.Person"/>
其中的Person类如下:
public class Person{
private final String firstName;
private final String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
}
2 . 那么如何使用呢,如上代码中的TextView中我们使用了@{}方式如下:
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{person.firstName}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{person.lastName}"/>
其中@{person.firstName}就是讲Person中的firstName赋值给第一个TextView,同理@{person.lastName}是将Person中的lastName赋值给第二个TextView;
3 . 那么这样就行了吗?显然是不行的,因为我们还没有吧person传到view中,那么我们如何传递person呢,其实当我们在data中使用variable标签时,databinding就已经给我们生成了binding.setPerson(Person)方法,也即会为每一个variable中生成对应的setXXX()方法;我们只需要在Java代码中调用即可,那么这个binding又如何获取呢,只需要使用DataBindingUtil.setContentView方法就可以返回一个binding,如下;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
Person person = new Person("Hello", "World");
binding.setPerson(person);
}
**这里要说一下生成的相关规则:使用DataBindingUtil.setContentView();生成的binding名称规则是其中的布局文件名后加上Binding即可:
MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
**也可以通过data元素的class设置他的名称
<data class="ClassNameTest">
...
</data>
Java代码:
ClassNameTest binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
**如果xml中的view设置了id,那么binding也会生成以id名为名的binding属性如下:
<TextView
android:id="@+id/test_tv"
android:layout_width="match_parent"
android:layout_height="30dp"
android:gravity="center"
/>
java中调用该TextView如下:
binding.testTv.setText("hellow world");
4 .最后运行一下APP即可
三、DataBinding的表达式用法
1. databinding的表达式跟Java的很相似:
* 数学 + - / * %
* 字符串连接 +
* 逻辑 && ||
* 二进制 & | ^
* 一元运算 + - ! ~
* 移位 >> >>> <<
* 比较 == > < >= <=
* instanceof
* 分组 ()
* null
* Cast
* 方法调用
* 数据访问 []
* 三元运算 ?:
事例代码如下:
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@{String.valueOf(2+2)}"
android:visibility="@{2==3 ? View.GONE : View.VISIBLE}"
/>
2.当然也有些暂时不支持的如下:
this
super
new
显式泛型调用
3.Null合并操作XX??XX
- 左边的对象如果它不是null,选择左边的对象;或者如果它是null,选择右边的对象:
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@{person.personName??person.lastName}"
/>
也就是 android:text=”@{person.personName==null?person.personName:person.lastName}”
**值得提一下的是:Data Binding代码生成时自动检查是否为nulls来避免出现null pointer exceptions错误。例如,在表达式@{user.name}中,如果user是null,user.name会赋予它的默认值(null)。如果你引用user.age,age是int类型,那么它的默认值是0。
四、DataBinding的集合的应用
databinding中常用的集合:arrays、lists、sparse lists以及maps,为了简便都可以使用[ ]来访问。
<data>
<import type="android.util.SparseArray"/>
<import type="java.util.Map"/>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/>
<variable name="sparse" type="SparseArray<String>"/>
<variable name="map" type="Map<String, String>"/>
<variable name="index" type="int"/>
<variable name="key" type="String"/>
</data>
…
android:text="@{list[index]}"
…
android:text="@{sparse[index]}"
…
android:text="@{map[key]}"
**这里要注意map集合的使用
使用单引号包裹最外层,使用双引号包裹属性名
android:text='@{map["firstName"]}'
五、DataBinding中include的使用
在databinding中是支持include属性的用法基本是一样的只是要加入bind属性:
事例代码:
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="person"
type="test.collyellow.runhua.databinding.Person" />
<variable
name="precenter"
type="test.collyellow.runhua.databinding.MainActivity.Precenter"/>
</data>
<LinearLayout
...
<include layout="@layout/incluce_demo" bind:person="@{person}"/>
</LinearLayout>
</layout>
include_demo.xml
<?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="person"
type="test.collyellow.runhua.databinding.Person" />
</data>
<LinearLayout
...
</LinearLayout>
</layout>
六、DataBinding的Observable使用
Data Binding的真正能力是当数据变化时,可以通知给你的Data对象。有三种不同的数据变化通知机制:Observable对象、ObservableFields以及observable collections。
1 .Obervable:
** 只需要让你的Data(bean)类,继承Observable即可,这里DataBinding个我们提供了一个BaseObservable的基类;然后在getter方法上指定一个Bindable注解,在在setter方法中调用notifyPropertyChanged()方法即可;
事例代码如下:
public class Person extends BaseObservable {
private String personName;
private int personAge;
public Person(String personName, int personAge) {
this.personName = personName;
this.personAge = personAge;
}
@Bindable
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
notifyPropertyChanged(test.collyellow.runhua.databinding.BR.personName);
}
**这里说明一下test.collyellow.runhua.databinding.BR是databinding给我们自动生成的类,里面包含了添加了Bindable注解的属性名,有时候可能需要编译才成功,这样当我们调用person.setXXX()方法时,就会给一个通知XXX属性已经发生了变化,需要更新;当然如果我们不想用Bindable注解,也可以使用notifyChange()方法来刷新所有属性值;
2 .ObservableFields
如果想要节省时间或者几乎没有几个属性的开发者可以使用ObservableFields。ObservableFields是自包含具有单个字段的observable对象。它有所有基本类型和一个是引用类型。要使用它需要在data对象中创建public final字段:
private static class Person{
public final ObservableField<String> firstName =
new ObservableField<>();
public final ObservableField<String> lastName =
new ObservableField<>();
public final ObservableInt age = new ObservableInt();
}
就是这样,要访问该值,使用set和get方法:
person.firstName.set("Google");
int age = person.age.get();
也即该类字段是通过自己的set、get方法来设置或者获取值;
3 .Observable 集合
一些app使用更多的动态结构来保存数据。Observable集合允许键控访问这些data对象。ObservableArrayMap用于键是引用类型,如String。
ObservableArrayMap<String, Object> map= new ObservableArrayMap<>();
map.put("firstName", "Google");
map.put("lastName", "Inc.");
map.put("age", 17);
然后在XML中使用
<TextView
android:text='@{map["lastName"]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
以上就是DataBinding的基本使用
参考
http://www.jianshu.com/p/b1df61a4df77
https://developer.android.com/topic/libraries/data-binding/index.html