构建环境
android{
dataBinding{
enabled = true
}
}
数据绑定布局文件
<?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标签里声明数据变量,数据类型可以是POJO类,也可以是JavaBeans类
绑定数据
默认情况下,将根据布局文件的名称生成一个Binding类,所以可以利用这个bingding类做绑定操作
例:
@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);
}
也可以通过以下几种方式获取binding实例
- MainActivityBinding binding = MainActivityBinding.inflate(getLayoutInflater());
- ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
- ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
事件处理
两种方式
- 方法引用:先在要绑定的数据类里声明事件要触发的方法,然后布局里直接调用声明的方法,比如:
public class MyHandlers {
public void onClickFriend(View view) { ... }
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="handlers" type="com.example.Handlers"/>
<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>
不过这种需要View控件已有onClick方法,而且也要注意方法的View参数对应上
- 监听器绑定
在方法引用中,方法的参数必须与事件侦听器的参数相匹配。在侦听器绑定中,只有您的返回值必须与侦听器的预期返回值相匹配(除非它是期望的void)
public class Presenter {
public void onSaveClick(Task task){}
}
<?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="@{() -> presenter.onSaveClick(task)}" />
</LinearLayout>
</layout>
可以注意到xml的onClick后面使用的lambda表达式,所以也可以写成: android:onClick="@{(view) -> presenter.onSaveClick(task)}"
布局详情
imports
可直接导入类
例:
<data>
<import type="android.view.View"/>
</data>
为什么?因为下面的控件标签要用
例:
<TextView
android:text="@{user.lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>
如果导入多个类,但类名相同,可以加个alias=""用于区分
也可以在声明variable时type类型名全部加上
自定义binding类名字
在data标签里 加class可改
<data class="ContactItem">
...
</data>
<data class=".ContactItem">
...
</data>
<data class="com.example.ContactItem">
...
</data>
包含
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/name"
bind:user="@{user}"/>
<include layout="@layout/contact"
bind:user="@{user}"/>
</LinearLayout>
</layout>
表达式
- 数字的+ - /* %
- 字符串 +
- 逻辑 && ||
- 二进制 & | ^
- 一元 + - ! ~
- 转移 >> >>> <<
- 比较 == > < >= <=
- instanceof
- Grouping()
- 子面
- cast
- 方法调用
- 域访问
- 数组访问
- 三元: ?:
例
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'
- 空合并运算符(??)选择左操作数,如果它不为空,或者如果为空则选择右操作数。
android:text="@{user.displayName ?? user.lastName}"
= android:text="@{user.displayName != null ? user.displayName : user.lastName}"