Google在2015年的I/O大会上发布了三个重要的支持库:
- Material Design支持库:Android Support Design
- 百分比布局支持库:Percent support lib
- 数据绑定支持库:Data Binding Library
-
是官方支持的MVVM模式框架
-
可以直接在静态布局XML中绑定数据,无需再findViewById,然后再手动设置数据
Question:是不是RoboGuice、AndroidAnotations...这样的依赖注入框架会慢慢淡出市场
-
可以提高解析XML的速度
-
UI与功能解耦
- Android Studio 1.3.0-beta1 或更高版本
- Gradle plugin 1.3.0以上
- Android 2.1(API level 7+)以上
在工程的根build.gradle文件中配置如下:
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
classpath 'com.android.databinding:dataBinder:1.+'
}
在app的build.gradle文件中配置如下:
apply plugin: 'com.android.application'
apply plugin: 'com.android.databinding'
只需要在app的build.gradle文件中如下配置就ok:
android {
....
dataBinding {
enabled = true
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://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>
public class User {
public final String firstName;
public final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
@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);
<data>
<import type="com.example.MyStringUtils"/>
<variable name="user" type="com.example.User"/>
</data>
<TextView
android:text="@{MyStringUtils.capitalize(user.lastName)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<data>
<import type="archmages.github.databindingsamples.model.User"/>
<import type="archmages.github.databindingsamples.model.real.User" alias="RealUser"/>
<variable
name="user"
type="RealUser"/>
</data>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='@{user.firstName}'/>
空聚合运算操作(??), 如果左边的运算对象不为空的话选择左边,否则选择右边
android:text="@{user.displayName ?? user.lastName}"
这个运算等价于:
android:text="@{user.displayName != null ? user.displayName : user.lastName}"
如下,我们要使用View的Visible属性:
<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}"/>
Data Binding也是支持直接访问资源数据的
android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"
Data Binding 有效降低了代码的冗余性,甚至完全没有必要再去获取一个 View 实例,万一我们真的就需要的时候,只要给 View 定义一个 ID,Data Binding 就会为我们生成一个对应的 final 变量。
<layout xmlns:android="https://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}"
android:id="@+id/firstName"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"
android:id="@+id/lastName"/>
</LinearLayout>
</layout>
Data Binding会自动生成成员变量 :
public final TextView firstName;
public final TextView lastName;
这样我们通过binding对象,可以直接访问这些View, 如此之方便
如果我们在ListView中或者在RecyclerView中使用Data Binding, 我们需要在Adapter中这样写(以ListView为例):
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()),
R.layout.user_list_item_view, viewGroup, false);
binding.setVariable(BR.user, users.get(i));
binding.executePendingBindings();
return binding.getRoot();
}
有时候我们为了避免layout的xml写得过长,有一些共用的View会抽出来,通过include的方式加入xml中,Data Binding也支持include binding, 我们如何传递binding给include layout呢? 通过Application命名空间 bind:
和变量名@{...}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:bind="https://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>
Data Binding自动会检查空对象并且避免空指针异常,例如:在表达式:@{user.name}
中,如果user
是null, user.name
会被指定一个默认值null
, 如果我们用@{user.age}
, 这个地方age是int型,那么当user为null的时候,user.age
默认是0
常用集合类型,Data Binding都支持:arrays, lists, sparse lists, and maps
<data>
<import type="android.util.SparseArray"/>
<import type="java.util.Map"/>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/>
<variable name="sparse" type="SparseArray<String>"/>
<variable name="map" type="Map<String, String>"/>
<variable name="index" type="int"/>
<variable name="key" type="String"/>
</data>
android:text="@{list[index]}"
android:text="@{sparse[index]}"
android:text="@{map[key]}"
[备注]
这边大家注意:在xml中<
是特殊字符,当引用List, Map...时,左尖括号需要用转义字符<
替换, 同时,引号"
要用"
替换
- Mathematical + - / * %
- String concatenation +
- Logical && ||
- Binary & | ^
- Unary + - ! ~
- Shift >> >>> <<
- Comparison == > < >= <=
- instanceof
- Grouping ()
- Literals - character, String, numeric, null
- Cast
- Method calls
- Field access
- Array access []
- Ternary operator ?:
- 目前Android Databinding还只支持单向绑定,试想未来是否能像Angular.Js一样支持双向绑定呢?
- 由于目前Android Data Binding还是测试版,buck官方说等Android Databinding升级到正式版本后才考虑对其支持
我谷歌大法一直在与时俱进,每年的I/O大会都会给出重量级的产品,期待上述两个Features的实现,如果真是这样的话,Android不管是开发速度还是编译速度都飞速提高😀