写在前面
2015年的Google IO大会上,Android团队发布了一个官方的数据绑定框架(Data Binding Library)。通过这个框架可以直接在layout布局文件中绑定数据,无需再写繁琐的findViewById,可以为我们省下大量的样板代码;更进一步的,可以直接通过更改数据来改变视图,把繁琐的事情交给Data Binding Library。
本文结合DataBindingDemo介绍怎么使用Data Binding Library。文中的例子可前往DataBindingDemo查看。
配置环境
Data Binding Library是一个support库,最低支持到Android 2.1(API level 7+)。
-
要使用data binding需要将Gradle升级到1.5.0-alpha1或者更新的版本,Android Studio升级到1.3或者更新的版本。
-
通过Android SDK Manager下载最新的Support repository
-
需要在module的build.gradle中配置允许data binding
android {
....
dataBinding {
enabled = true
}
}
注意:如果你的app module中依赖了使用data binding的库,app的build.gralde中也要配置允许data binding
Data Binding布局文件
data binding布局文件不再纯粹展示UI的布局,而是添加了UI需要用的数据。所以根节点变成layout
标签,并且新增了一个节点data
。data
节点之后才是view
节点。
<?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
里面的variable
标签用于描述在布局里可能用到的属性。
布局文件中的表达式用"@{}"语法。
数据对象
假设你有一个POJO(plain-old Java object)的User类:
public class User {
public final String firstName;
public final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
或者声明一个JavaBeans类型的User类:
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是没有区别的。上文android:text="@{user.lastName}"
用到的lastName,data binding会读取POJO类的lastName,或者JavaBeans的getLastName()。
绑定数据
默认情况下,在写完布局文件之后,data binding会自动生成一个以Binding结尾的Binding类,例如布局文件的名称是activity_main.xml
,生成的Binding类是ActivityMainBinding.java。对于布局文件里面声明的variable
,Binding类会自动生成setter、getter。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
User user = new User("Bai", "Li");
binding.setUser(user);
}
DataBindingUtil提供了setContentView代替之前的setContentView方法,用于生成一个Binding类。也可用inflate
方法:
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
如果使用data binding的布局是用于ListView
或者RecycleView
的items,用法稍有不同:
ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
//or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
事件处理
除了绑定数据,Data Binding也可以响应视图的事件。有两种方式:
- 方法调用 ---- 在编译时处理
- 监听绑定 ---- 在事件触发时处理
方法调用
创建一个EventHandler类:
public class EventHandler {
ActivityEventHandlingBinding mBinding;
public EventHandler(ActivityEventHandlingBinding binding) {
this.mBinding = binding;
}
/**
* 方法调用
*
* @param view
*/
public void onClick(View view) {
mBinding.setUser(new User("bai", "li"));
}
}
在布局文件的data
节点中声明:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.dragonjiang.databindingdemo.model.User" />
<variable
name="handler"
type="com.dragonjiang.databindingdemo.handler.EventHandler" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName + ` ` + user.lastName}" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{handler::onClick}"
android:text="method references" />
</LinearLayout>
</layout>
注意:android:onClick
对应于java的OnClickListener#onClick(View view)
,因此EventHandler类里面的onClick(View view)也要有相同的参数。
监听绑定
其用法如下:
public class EventHandler {
ActivityEventHandlingBinding mBinding;
public EventHandler(ActivityEventHandlingBinding binding) {
this.mBinding = binding;
}
/**
* 事件绑定
*
* @param user
*/
public void onClickEvent(User user) {
User u = new User("pu", "du");
mBinding.setUser(u);
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.dragonjiang.databindingdemo.model.User" />
<variable
name="handler"
type="com.dragonjiang.databindingdemo.handler.EventHandler" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName + ` ` + user.lastName}" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{()->handler.onClickEvent(user)}"
android:text="listener bindings" />
</LinearLayout>
</layout>
如果你要在onClickEvent
里面使用参数,可以采用如下写法:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{(view)->handler.onClickEventWithParams(view, user)}"
android:text="listener bindings with params" />
当然,参数view
要嘛不写,要嘛有多个参数就要写全。参数名可以自己定义。例如:
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onCheckedChanged="@{(cb, isChecked) -> handler.onCheckBoxChanged(cb, isChecked)}" />
至此,Android Data Binding的简单入门就介绍完了。我们将在下一篇文章介绍data binding的进阶知识:
Android Data Binding——进阶
网友评论