数据绑定框架DataBinding--入门篇
一、描述
MVC,MVP都是大家所熟知的,而今天的主题的MVVM数据绑定,这个是最新推出的框架,刚加入公司没多久,看公司里的同事再用这个,所以我熟悉之后发现确实挺好用的,在这里分享给大家。
二、引用
Data Binding自从去年的Google I/O发布到至今,也有近一年的时间了。这一年来,从Beta到如今比较完善的版本,从Android Studio 1.3到如今2.1.2的支持,可以说Data Binding已经是一个可用度较高,也能带来实际生产力提升的技术了。
而事实上,真正使用到Data Binding的公司、项目仍然是比较少的。可能是出于稳定性考虑,亦或是对Data Binding技术本身不够熟悉,又或许对新技术没什么追求。
我司在新的产品中就全面使用了Data Binding技术,无论是我,还是新来直接面对Data Binding上手的工程师也好,都对其爱不释手,用惯了后简直停不下来。
希望在看完本文的介绍后,会有更多的朋友产生兴趣,来使用Data Binding,参与它的讨论。
三、什么是DataBinding
</br>
这里我以我的理解来说,就是一个或者多个实体对象对应着一个页面,实体中的某些属性绑定着页面上的控件,当属性的值改变时,页面上的控件会自动更新数据。
四、效果展示
</br>
</br>
没用DataBinding之前
</br>
XML布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.junwen.databinding.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="姓名:" />
<TextView
android:id="@+id/activity_main_stu_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="学生姓名" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="年龄:" />
<TextView
android:id="@+id/activity_main_stu_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="学生年龄" />
</LinearLayout>
<Button
android:id="@+id/activity_main_stu_setting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="更改姓名" />
</LinearLayout>
Student实体类
/**
* 描述:学生对象
* 作者:卜俊文
* 创建:2016/8/10 10:20
* 邮箱:344176791@qq.com
*/
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
MainActivity主页面
public class MainActivity extends AppCompatActivity {
private TextView tv_name; //学生姓名
private TextView tv_age; //学生年龄
private Button btn_setting; //设置
private Student student; //学生对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
initListener();
}
/**
* 描述:初始化控件
* 作者:卜俊文
* 邮箱:344176791@qq.com
* 创建时间: 2016/8/10 10:17
*/
private void initView() {
tv_name = (TextView) findViewById(R.id.activity_main_stu_name);
tv_age = (TextView) findViewById(R.id.activity_main_stu_age);
btn_setting = (Button) findViewById(R.id.activity_main_stu_setting);
}
/**
* 描述:初始化数据
* 作者:卜俊文
* 邮箱:344176791@qq.com
* 创建时间: 2016/8/10 10:19
*/
private void initData() {
//创建一个学生对象
student = new Student("俊文", 22);
//根据学生对象赋值到控件上
tv_name.setText(student.getName());
tv_age.setText(String.valueOf(student.getAge()));
}
/**
* 描述:初始化监听
* 作者:卜俊文
* 邮箱:344176791@qq.com
* 创建时间: 2016/8/10 10:22
*/
private void initListener() {
btn_setting.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//点击设置,更改Student对象的名字。
student.setName("卜俊文");
tv_name.setText(student.getName());
}
});
}
}
运用DataBinding
</br>
XML布局
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="student"
type="com.example.junwen.databinding.Student" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="姓名:" />
<TextView
android:id="@+id/activity_main_stu_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="@{student.name}" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="年龄:" />
<TextView
android:id="@+id/activity_main_stu_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="@{String.valueOf(student.age)}" />
</LinearLayout>
<Button
android:id="@+id/activity_main_stu_setting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="更改姓名" />
</LinearLayout>
</layout>
Student实体类
/**
* 描述:学生对象, @Bindable注解是为了能在BR里面找到这个属性 notifyPropertyChanged(); 这个方法是当调用的时候,会通知绑定的控件去改变值
* 作者:卜俊文
* 创建:2016/8/10 10:20
* 邮箱:344176791@qq.com
*/
public class Student extends BaseObservable {
@Bindable
private String name;
@Bindable
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(com.example.junwen.databinding.BR.name);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
notifyPropertyChanged(com.example.junwen.databinding.BR.age);
}
}
MainActivity主页面
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding activity_main_binding; //本页面的Binding对象
private Student student; //学生对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initListener();
}
/**
* 描述:初始化数据
* 作者:卜俊文
* 邮箱:344176791@qq.com
* 创建时间: 2016/8/10 10:48
*/
private void initData() {
//这个就类似于setContentView
activity_main_binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
student = new Student("俊文", 22);
//把Student对象绑定到布局的控件中去,现在开始只要student对象属性变化,控件的值也是相应改变
activity_main_binding.setStudent(student);
}
/**
* 描述:初始化监听
* 作者:卜俊文
* 邮箱:344176791@qq.com
* 创建时间: 2016/8/10 10:22
*/
private void initListener() {
activity_main_binding.activityMainStuSetting.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
student.setName("卜俊文");
}
});
}
}
五、优劣所在?
</br>
优势
</br>
(1) DataBinding不需要findviewbyId,只需要根据binding对象去查找到对应的控件。
(2)直接绑定一个对象到XML布局中,当对象的属性变化时,布局中的控件会马上同步变化。
(3)UI代码放到了xml中,布局和数据更紧密
劣势
</br>
(1)IDE支持还不那么完善(提示、表达式)
(2)报错信息不那么直接
六、开始编写
</br>
(1) 在app / build.gradle 中加入以下字段,即可使用DataBinding框架
</br>
dataBinding {
enabled = true
}
(2)编写XML,这里给出一个XML模版
</br>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="item"
type="com.example.junwen.databinding.Student" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{item.name}" />
</LinearLayout>
</layout>
此模块由<Layout>标签作为根节点,里面包含两部分,第一部分是<data>,第二部分就是<LinearLayout>,也就类似于以前我们写布局时的根布局。
其中<data>标签中可以声明对象,变量以及导入包等功能,在这里我导入了Student对象,在下面我需要用到我就可以导入进来,并且起成item的一个别名。
其中<LinearLayout>中,包含了一个TextView,这个TextView的text属性值是这样赋值的(格式必须对):
android:text="@{item.name}"
双引号中 " @{具体变量或者对象的属性值}" ,不只这些,还可以在里面运用表达式,例如上面的例子中的
android:text="@{String.valueOf(student.age)}"
这个能够在一个属性的后面添加字符串比如下面
android:text="@{item.progress+`%`}"
(3)编写MainActivity
</br>
(1)取得Binding对象,这个就类似于setContentView(),返回的对象其实是一个ViewDataBinding,但是我这里写的是ActivityMainBinding,你可以比较一下ActivityMainBinding 和 R.layout.activity_main有什么相似的地方吗?不错,就是拼接起来的,这样就可以获得这个页面的Binding对象。
ActivityMainBinding activity_main_binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
(2)创建一个Student对象,并且调用setStudent(student)方法,这个方法他会自动生成的,实现了实体与xml绑定。
Student student = new Student("俊文", 22);
//把Student对象绑定到布局的控件中去,现在开始只要student对象属性变化,控件的值也是相应改变
activity_main_binding.setStudent(student)
(3)设置监听,直接通过binding对象查询到按钮控件,这个activityMainStuSetting也会自动生成的,如果遇到没有生成,你需要build一下项目,他就会出来了,执行setName方法,在其内部就会去通知控件更新文本。
activity_main_binding.activityMainStuSetting.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
student.setName("卜俊文");
}
});
七、其他
</br>
操作符示例:
</br>
(1)判断属性赋值不同的图片
android:src="@{item.checkState.equals(String.valueOf(3)) ? @drawable/ic_task_exit : @drawable/ic_task_success }"
(2)设置不同的字符串
android:text='@{error ? "error" : "ok"}'
</br>
XML的DataBinding模版XML快速创建
</br>
1229.gif
关于DataBinding数据绑定
</br>
Android官方数据绑定框架DataBinding
</br>
从零开始的Android新项目7 - Data Binding入门篇
</br>
Android官方数据绑定框架DataBinding(一)
</br>
Android Data Binding代码实战
</br>
完全掌握Android Data Binding
</br>
数据绑定DataBinding
八、总结
在此就总结了一些基本的DataBind的用法,可能有些地方说的不到位的,也是刚接触不是很熟悉,就是凭自己的理解来说的。
欢迎关注我的微信公众号,分享更多技术文章。