写在前面
目前我们的项目采用的是mvp架构,而android系统本身设计的,很难实现mvvm。Data Binding这个support库可以很好的解决这个问题,做一点技术调研。读了些资料,写了点demo后,感觉特别清爽。
Data Binding是什么?
- 一个支持用最少代码绑定逻辑和layout文件的库
- 一个灵活广泛的support库(Google提供)
兼容
- Android 2.1 (API level 7+)及以上
- Android Studio版本:1.5.0-alpha1及以上(最新Data Binding版本)
为什么引入Data Binding(Data Binding做了什么)
- 谷歌官方出品必属精品
- 不再需要findViewById这样的样板代码(ButterKnife实际上也是做了这样的事情)
- 也不需要考虑线程切换问题
- 最酷的是数据自动分发
虽然这样的代码并没什么难度,省去这样的代码,让你的逻辑更加简洁易读;节省很多无脑代码,这样程序猴子只需要关注必须关注的逻辑和代码
构建环境
在模块的build.gradle文件中添加
android {
......
dataBinding {
enabled = true
}
}
ps: 有的文章中介绍需要引入其他的东西,经测试,这就足够了,不再需要别的
使用
先看一个简单例子
先从布局文件开始
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.view.View"/>
<variable name="user" type="com.example.User"/>
</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}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}" />
</FrameLayout>
</LinearLayout>
</layout>
标签
:根标签,约束也是在这里写
:layout的子标签,用于引入变量,声明变量
User代码如下(简单javabean)
public class User {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public User setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
public String getLastName() {
return lastName;
}
public User setLastName(String lastName) {
this.lastName = lastName;
return this;
}
}
Activity中绑定数据
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User user = new User();
user.setFirstName("first")
.setLastName("last");
viewDataBinding.setUser(user);
}
}
再看一下我们之前是如何实现这个功能的
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_first_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_last_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
在布局文件中,我们必须指定每一个控件的id
activity中的代码
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_old);
TextView tvFirstName = (TextView) findViewById(R.id.tv_first_name);
TextView tvLastName = (TextView) findViewById(R.id.tv_last_name);
User user = new User();
user.setFirstName("first")
.setLastName("last");
tvFirstName.setText(user.getFirstName());
tvLastName.setText(user.getLastName());
}
在activity中,我们必须通过id关联到对应的控件,然后在代码中对控件进行设置。
这个例子可以简单看出databinding的优势,MainActivity和UI相关(数据绑定)的操作只有
ActivityMainBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
viewDataBinding.setUser(user);
数据的填充放到了布局文件中,页面越复杂,databinding这种方式在简化逻辑上的优势越明显。
如果有所改动的话,databinding只需改动一下布局文件就好了,比传统的方式更灵活。
关于data标签
import
<import type="android.view.View"/>
data标签下使用import标签,就像导入java类一样导入第三方的类。
一个layout标签下可以有多个data标签
variable
<variable name="user" type="com.example.User"/> <variable name="image" type="Drawable"/> <variable name="note" type="String"/>
变量导入
data标签下使用variable标签,variable标签有两个属性
+ name
用以声明变量名
+ type
用以声明变量类型
一个layout标签下可以有多个variable标签
自定义绑定数据名称
data标签中class属性,Google提供了三种形式<data class="ContactItem">
自定义绑定数据名称为 包名.databinding.ContactItem
<data class=".ContactItem">
自定义绑定数据名称为 包名.模块名.ContactItem
<data class="com.example.ContactItem">
自定义绑定数据名称为 class指定名称
Includes 关联布局文件使用
引入 必须传递被引用layout文件需要的的数据
<include
layout="@layout/include_content"
bind:monkey="@{monkey}" />
include的文件
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="monkey"
type="com.vhawk.camera.gradletest.Monkey" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{monkey.habit}"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{monkey.play}"/>
</LinearLayout>
</layout>
引用出
逻辑运算
- 数学 + - / * %
- 字符串连接 +
- 逻辑 && ||
- 二进制 & | ^
- 一元运算 + - ! ~
- 移位 >> >>> <<
- 比较 == > < >= <=
- instanceof
- 分组 ()
- null
- Cast
- 方法调用
- 数据访问 []
- 三元运算 ?:
参考文档
https://developer.android.com/topic/libraries/data-binding/index.html
https://segmentfault.com/a/1190000002876984
https://realm.io/cn/news/data-binding-android-boyar-mount/
https://www.jayway.com/2015/12/08/recyclerview-and-databinding/