基础理解
DataBinding针对每个Activity的布局,在编译阶段,生成一个ViewDataBinding类的对象,该对象持有Activity要展示的数据和布局中的各个view的引用(也就解决了findViewById的问题),同时该对象还有将数据分解到各个view,在UI线程上更新数据,监控数据的变化,实时更新等功能,这样要展示的数据和展示它的布局就紧密的联系在一起了。
简单例子
首先我们先建立一个java bean。
public class User {
private String name;
private String age;
public User(String name, String age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(String age) {
this.age = age;
}
public String getName() {
return this.name;
}
public String getAge() {
return this.age;
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="user"
type="app.ylm.com.studyproject.User"/>
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="@{user.name}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="@{user.age}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</layout>
然后会自动生成Binding类,命名规则为:
xml通过文件名生成,使用下划线分割大小写,后缀加上Binding。比如activity_demo.xml,则会生成ActivityDemoBinding。在Activity中使用。
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DatabindingBinding binding = DataBindingUtil.setContentView(this,R.layout.databinding);
User user = new User("tony","12");
binding.setUser(user);
}
}
这样就可以使用了
主要组成部分
1、ViewDataBinding
数据绑定类的基类。
ViewDataBinding的实例一般是DataBindingUtil调用setContentView(Activity activity, int layoutId)方法生成。
2、BR
BR中的常量是一种标识符,它对应一个会发生变化的数据,当数据改变后,你可以用该标识符通知DataBinding,很快,DataBinding就会用新的数据去更新UI。
3、DataBindingUtil
可以从layout创建数据绑定类。
关于他们之间的关系可以看这篇
DataBinding实现原理探析
拓展
变量定义
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.graphics.Bitmap" />
<import type="java.util.ArrayList" />
<import type="java.util.HashMap" />
<!-- 集合的定义 -->
<variable
name="list"
type="ArrayList<String>" />
<variable
name="map"
type="HashMap<String, String>" />
<variable
name="array"
type="String[]" />
<!-- 为集合定义对应的索引 -->
<variable
name="listKey"
type="int" />
<variable
name="mapKey"
type="String" />
<variable
name="arrayKey"
type="int" />
<!-- 字符串,布尔值和int的用法-->
<variable
name="str"
type="String"/>
<variable
name="error"
type="boolean"/>
<variable
name="num"
type="int" />
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{list[listKey]}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{map[`name`]}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{array[0]}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{str}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(num)}"/>
</LinearLayout>
</layout>
事件的绑定
可以直接在 xml 导入android.view.View.OnClickListener,并制定其点击事件。
<variable
name="clickListener"
type="android.view.View.OnClickListener" />
...
android:onClick="@{clickListener}"
...
holder.binding.setClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//do something
});
表达式
在xml文件中还是支持表达式的,比如说如下:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{error ? "yes" : "no"}'/>
支持的表达式:
Mathematical + - / * %
String concatenation +
Logical && ||
Binary & | ^
Unary + - ! ~
Shift >> >>> <<
Comparison == > < >= <=
instanceof
Grouping ()
Literals - character, String, numeric, null
Cast
Method calls
Field access
Array access []
Ternary operator ?:
使用类方法
比如User中有一个静态方法
public static String getLevel(){
return "0";
}
然后在 xml 的 data 节点中导入:
<import type="app.ylm.com.studyproject.User"/>
使用方法与 Java 语法一样:
<TextView
android:text="@{User.getLevel()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Observable Binding
要实现 Observable Binding,首先得有一个实现了 android.databinding.Observable 的类,为了方便,Android 原生提供了已经封装好的一个类 - BaseObservable,并且实现了监听器的注册机制。
public class ObservableUser extends BaseObservable {
private String firstName;
private String lastName;
@Bindable
public String getFirstName() {
return firstName;
}
@Bindable
public String getLastName() {
return lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
notifyPropertyChanged(BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
notifyPropertyChanged(BR.lastName);
}
}
通过代码可以看出,当数据发生变化时还是需要手动发出通知。 通过调用notifyPropertyChanged(BR.firstName)来通知系统 BR.firstName 这个 entry 的数据已经发生变化,需要更新 UI。