本文参考databinding官方文档整理。官方文档链接地址https://developer.android.com/topic/libraries/data-binding/index.html#data_binding_layout_files
Data Binding框架作为官方推荐的MVVp框架已经出现很久,也越来越成熟稳定。android开发这些年从MVC到MVP,再到MVVP,开发手段不断更新,各大公司对代码逻辑性要求越来越高。Data Binding作为一种主流,我们都应该抱着学习的心态了解它,就算我们不深入使用,也能用它来代替无聊的findViewById吧。
一、工程中引入Data Binding库
Android Studio 1.3以后,build.gradle文件中android标签增加以下代码:
android { .... dataBinding { enabled = true } }二、使用举例
1、先定义一个实体类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; } }2、布局文件activity_main.xml中绑定User对象。此处需要注意,其实标签变为layout,<data>标签中定义ViewModel名字和类型。需要注意的是<variable>还能定义基本数据类型,比如String、int、boolean、Drawable等,后面会举例使用。
<?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>3、Activity中实例化一个User对象,绑定到布局文件。MainActivityBinding是databinding框架根据activity_main.xml自动生成的类。绑定成功后修改user中的字段firstName、lastName,对应的TextView会自动同步最新数据。
@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); }
1、先定义一个Presenter类
public class Presenter {
public void onSaveClick(Task tas){
//处理按键点击事件
}
public boolean onLongClick(View view, Task task){ }
public void onCompletedChanged(Task task, boolean completed){}
}
2、布局文件中绑定。此处可以看出,Data Binding支持
lambda 表达式,点击事件支持传递参数task。不使用lambda表达式时候可以写成android:onClick="@{(view) -> presenter.onSaveClick(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:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}" android:onClick="@{() -> presenter.onSaveClick(task)}" /> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}" /> </LinearLayout> </layout>
支持导包,通过上面两个例子可以发现Data Binding能想java文件一样导包,所以我们可以导入一些已存在的类来控制UI显示。
1、导入View控制可见性
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.view.View"/>
<variable name="visibility" type="boolean" />
</data>
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="@{user.lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{visibility ? View.VISIBLE : View.GONE}"/>
</LinearLayout>
</layout>
2、xml文件定义了一个名为visibility的boolean变量,使用对应的binding对象(MainActivityBinding)时候,可以MainActivityBinding.visibility设置值,对应的TextView会自动隐藏、可见。
看到这里你可能已经发行,上面所举栗子里面使用到了?表达式。确实,data binding支持在xml文件中使用表达式,利用这些表达式可以在xml文件中处理很复杂的界面逻辑,这里就不举例说明,copy一份官方列举的表达式供大家参考,大部分跟java一样或者类似:
- Mathematical
+ - / * %
- String concatenation
+
- Logical
&& ||
- Binary
& | ^
- Unary
+ - ! ~
- Shift
>> >>> <<
- Comparison
== > < >= <=
instanceof
- Grouping
()
- Literals - character, String, numeric,
null
- Cast
- Method calls
- Field access
- Array access
[]
- Ternary operator
?:
Include标签的使用
1、bind:user为子布局中定时的属性名,子布局写法跟普通data binding布局一样写法。
<?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>2、不支持include merge组合的一种使用方式
<?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> <merge> <include layout="@layout/name" bind:user="@{user}"/> <include layout="@layout/contact" bind:user="@{user}"/> </merge> </layout>