Data Binding 是 google 推出的布局与数据做双向绑定的库。它是一个 support library,可以在 Android 2.1 (API level 7+)以上的平台使用,同时 Android Plugin for Gradle 的版本必须是 1.5.0-alpha1 以上。
编译环境
在build.gradle
中添加:
1 2 3 4 5 6
| android { .... dataBinding { enabled = true } }
|
有一点要注意,如果 library 项目中使用了 data binding,app 项目必须也得在build.gradle
中声明以上配置。
基本使用
这里分三部分来讲解:1、model 类;2、布局文件;3、activity/fragment
model 类的定义
定义一个 POJO(plain-old Java object),形如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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; } }
|
布局文件
使用一个名为layout
的根节点编写我们以往的 layout 文件,在data
节点内声明我们要绑定的数据,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?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 name="user" type="com.example.User"/>
描述了此 layout 文件要使用的 model,在TextView
的使用形如@{user.firstName}
来设置 text。
activity/fragment
通常情况下,as 会根据我们刚才编写的 layout 文件自动生成一个 Binding class,如果 layout 文件为activity_main.xml
,则生成的 class 就命名为ActivityMainBinding
。然后我们需要在代码中使用这个类来做数据绑定:
1 2 3 4 5 6 7 8 9
| @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity); User user = new User("Test", "User"); binding.setUser(user); }
|
如果我们是在 ListView 或 RecyclerView 的 adapter 中要使用 data binding,如下使用:
1 2 3
| ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
|
Data Binding 提供了两种方式来做事件绑定和处理:Method References
和Listener Bindings
。
这两种方式最主要的区别在于:Method References
是当数据被绑定时就创建了对应的 listener,而Listener Bindings
则是当事件发生时创建。
Method References
定义一个用来处理事件的类:
1 2 3
| public class MyHandlers { public void onClickFriend(View view) { ... } }
|
layout 文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="handlers" type="com.example.MyHandlers"/> <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}" android:onClick="@{handlers::onClickFriend}"/> </LinearLayout> </layout>
|
此方式必须保证类中的方法签名和对应 listener 的签名保持一致,否则在编译期间会报错。
Listener Bindings
此种方式和method references
类似,也是定义一个类来处理事件,区别是在 xml 中使用 lambda 表达式来声明,而且只需要类的返回类型和 listener 一致即可。
1 2 3
| public class Presenter { public void onSaveClick(View view, Task task){} }
|
1 2 3 4 5 6 7 8 9 10 11
| <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="task" type="com.android.example.Task" /> <variable name="presenter" type="com.android.example.Presenter" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{(v) -> presenter.onSaveClick(v, task)}" /> </LinearLayout> </layout>
|
如果要在表达式中使用断言,我们可以使用void
作为一个符号:
1
| android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"
|
参考文章:
http://yanghui.name/blog/2016/02/17/data-binding-guide/ > https://developer.android.google.cn/topic/libraries/data-binding/index.html