Data Binding
Data Binding即数据绑定,Data Binding 库实现在布局文件中实现数据绑定申明,使数据的变化引起视图的自动更新,减少了逻辑代码,在Android中可以很方便的实现MVVM的开发模式。
MVVM
了解MVVM之前,我们先简单说一下MVC、MVP模式。
MVC是Model(模型)---View(视图)---(Controller)控制器的缩写,它用一种将业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。将系统进行MVC分层的核心思路就是分离组件,降低组件耦合性,组件独立演化。
MVP是Model--View--Presenter的缩写,MVP与MVC的主要区别是在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。模型与视图完全分离,我们可以修改视图而不影响模型,可以更高效地使用模型,因为所有的交互在Presenter里面。
MVVM是Model-View-ViewModel的缩写,Model提供数据、View负责显示、ViewModel负责逻辑的处理,与MVP的区别是,ViewModel与View之间采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之ViewModel的变化自动引起View的改变 。ViewModel作为View的数据映射,通常View上有什么属性,ViewModel上也会存在相应的一个属性,这两个属性通过事件实现了双向的绑定,Data Binding Library 替我们完成了这样的绑定过程。 MVVM的几个优点:
1. 低耦合: 视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变 化的时候Model可以不变,当Model变化的时候View也可以不变。
2. 可重用性: 你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
3. 可测试: 界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。
环境搭建
Data Binding 插件需要Gradle 1.3以上及Android Studio 1.3.
配置Guide文件:添加Data binding 包路径
[plain] view plain copy print ?
1. buildscript {
2. repositories {
3. jcenter()
4. }
5. dependencies {
6. classpath "com.android.tools.build:gradle:1.3.0-beta1"
7. classpath "com.android.databinding:dataBinder:1.0-rc0"
8.
9. }
10. }
然后确保jcenter是在子项目的库列表中
<span style="font-size: 18px;"><span class="pln"><span style="white-space: pre;"> </span>allprojects </span><span class="pun" style="color: rgb(102, 102, 0);">{</span><span class="pln">
<span style="white-space: pre;"> </span> repositories </span><span class="pun" style="color: rgb(102, 102, 0);">{</span><span class="pln">
<span style="white-space: pre;"> </span> jcenter</span><span class="pun" style="color: rgb(102, 102, 0);">()</span><span class="pln">
<span style="white-space: pre;"> </span> </span><span class="pun" style="color: rgb(102, 102, 0);">}</span><span class="pln">
</span><span class="pun" style="color: rgb(102, 102, 0);"><span style="white-space: pre;"> </span>}</span></span>
在android插件后面添加dataBinding插件
<span class="pln"><span style="white-space: pre;"> </span>apply plugin</span><span class="pun" style="color: rgb(102, 102, 0);">:</span><span class="pln"> </span><span class="pun" style="color: rgb(102, 102, 0);">‘</span><span class="pln">com</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln">android</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln">application</span><span class="str" style="color: rgb(136, 0, 0);">'
<span style="white-space: pre;"> </span>apply plugin: '</span><span style="color: inherit;"><span class="pln">com</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln">android</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln">databinding</span></span><span class="str" style="color: rgb(136, 0, 0);">'</span>
如何使用Data Binding
支持 Data Binding的布局文件和以前的布局文件不一样,它的跟节点不再是一个ViewGroup,而是layout,并且多了一个data节点。
[plain] view plain copy print ?
1. <?xml version="1.0" encoding="utf-8"?>
2. <layout xmlns:android="http://schemas.android.com/apk/res/android">
3. <data>
4. <variable name="user" type="com.example.User"/>
5. </data>
6. <LinearLayout
7. android:orientation="vertical"
8. android:layout_width="match_parent"
9. android:layout_height="match_parent">
10. <TextView android:layout_width="wrap_content"
11. android:layout_height="wrap_content"
12. android:text="@{user.firstName}"/>
13. <TextView android:layout_width="wrap_content"
14. android:layout_height="wrap_content"
15. android:text="@{user.lastName}"/>
16. </LinearLayout>
17. </layout>
在data节点里面的variable声明实现数据与UI的绑定,变量为UI提供数据,通过@{ } 可以直接把Java 中定义的属性赋值给UI:
[plain] view plain copy print ?
1. <span > </span>android:text="@{user.firstName}
数据对象
任何Java对象对象(POJO)可以做数据绑定。
[java] view plain copy print ?
1. public class User {
2. private final String firstName;
3. private final String lastName;
4. public User(String firstName, String lastName) {
5. this.firstName = firstName;
6. this.lastName = lastName;
7. }
8. public String getFirstName() {
9. return this.firstName;
10. }
11. public String getLastName() {
12. return this.lastName;
13. }
14. }
这种绑定以后成员属性改变却不会让UI进行更新。
要实现成员变更时,UI随着自动更新,首先得有一个实现了 android.databinding.Observable 的类,Android 原生提供了已经封装好的一个类 - BaseObservable,并且实现了监听器的注册机制。 数据类的实现者仍然有责任让成员属性变化时进行通知。这是通过指派一个Bindable注解到getter方法上完成的,并且需要在setter中完成通知动作。
[java] view plain copy print ?
1. private static class User extends BaseObservable {
2. private String firstName;
3. private String lastName;
4. @Bindable
5. public String getFirstName() {
6. return this.firstName;
7. }
8. @Bindable
9. public String getFirstName() {
10. return this.lastName;
11. }
12. public void setFirstName(String firstName) {
13. this.firstName = firstName;
14. notifyPropertyChanged(BR.firstName);
15. }
16. public void setLastName(String lastName) {
17. this.lastName = lastName;
18. notifyPropertyChanged(BR.lastName);
19. }
20. }
BR 是编译阶段生成的一个类,功能与 R.java 类似,用 @Bindable 标记过 getter 方法会在 BR 中生成一个 entry,当我们通过代码可以看出,当数据发生变化时还是需要手动发出通知。 通过调用notifyPropertyChanged(BR.firstName)来通知系统 BR.firstName 这个 entry 的数据已经发生变化,需要更新 UI。
绑定数据
默认情况下,一个绑定类会根据布局文件的名称生成一个绑定类,下面代码就是activity_main.xml生成的类ActivityMainBinding.这个类持有所有从布局文件中的View对应的属性(例如:user变量),并且知道如何指派变量值到绑定的表达式中。
[java] view plain copy print ?
1. @Override
2. protected void onCreate(Bundle savedInstanceState) {
3. super.onCreate(savedInstanceState);
4. this, R.layout.main_activity);
5. new User("Test", "User");
6. binding.setUser(user);
7. }
官方手册:
https://developer.android.com/tools/data-binding/guide.html