您的位置:首页 > 移动开发 > Android开发

Android DataBinding

2016-05-16 11:08 519 查看

0、前言

Android传统框架中,Activity承载了太多的任务,业务逻辑的处理、view逻辑处理等等都写在Activity中,代码过于臃肿耦合。Fragment出现后,臃肿情况稍微好转一点,毕竟代码大都迁移到了Fragment中。我们可以对Fragment再次进行分块,进一步降低代码臃肿现象,但是代码耦合的现象仍然无法得以解决。

Google官方提供的基于MVVM架构Data Binding框架,一定程度上有效解决了问题,而且对于现有框架的侵入几乎没有。

1、准备工作

(1)Android Studio 需要版本1.3及以上

(2)Gradle 需要版本1.5.0及以上

(3)module build.gradle 添加data binding配置

android {
....
dataBinding {
enabled = true
}
}


2、入门

(1)首先定义一个简单的model-com.example.User。

public class User {
public String firstName;
public String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}


(2)布局文件data_bind_test.xml,写法有所改动,导入Model可以直接对View进行数据绑定。

<?xml version="1.0" encoding="utf-8"?>
// 根节点必须为layout,表明这是一个data binding布局文件;
<layout xmlns:android="http://schemas.android.com/apk/res/android">
// 可指定class属性,即自动生成的ViewDataBinding名称;如果未指定,根据布局文件名生成,例如:DataBindTestBinding
<data class="com.example.UserDataBinding">
<import type="com.example.StringUtil" alias="StringFormatUtil" /> // 导入工具类
<variable name="user" type="com.example.User"/>  // 声明Model变量
<variable name="sex" type="String"/>  // 也可以声明基本类型或者String类型变量
</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}"/>   //直接绑定model数据
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{sex}"/>     //基本类型数据
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{StringFormatUtil.format(user.lastName)}"/>   //使用导入的工具类
</LinearLayout>
</layout>


当import两个同名不同包的Java class时,框架是无法区分的,这时可以使用alias 属性指定一个别名来进行区分,这点和Mybatis框架相似!

官方文档上还介绍了data binding框架可以直接为view 绑定事件监听,例如onClick单击事件、onLongClick长按事件。但是试验下发现,没有效果,可能测试的框架版本还没有支持。

(3)以上两步,已经将view和model进行了绑定,但是数据从哪里来呢?

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 返回ViewDataBinding,并将rootView添加到activity布局中
UserDataBinding binding = DataBindingUtil.setContentView(this, R.layout.data_bind_test.xml);
User user = new User("Kobe", "Bryant");
binding.setUser(user);
}


DataBindingUtil类的setContentView方法可以返回指定布局生成的ViewDataBinding,ViewDataBinding会根据布局文件声明的变量,自动为我们生成setter接口,直接传入数据即可。

获取ViewDataBinding还可以有以下方式:

// 只inflate布局,返回ViewDataBinding
UserDataBinding binding = UserDataBinding.inflate(getLayoutInflater());

或者

// 在ListView、RecyclerView的Adapter中使用如下方法
UserDataBinding binding = UserDataBinding.inflate(layoutInflater, viewGroup, false);
//or
UserDataBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.data_bind_test.xml, viewGroup, false);


如果想获取到inflate的view,可以使用ViewDataBinding.getRoot()方法。

3、Observable

现在View已经可以加载Model的数据了,但是当Model发生改变时,发现View并没有更新。Data Binding框架把这部分工作交由我们自己来实现,提供了以下几种实现方式供我们选择。

(1)实现Observable接口

Model改变时,手到调用方法进行notify。为了方便,框架已经帮我们封装了下,提供了BaseObservable类,我们的Model直接extends就好。

private static class User extends BaseObservable {
private String firstName;
private String lastName;
@Bindable
public String getFirstName() {
return this.firstName;
}
@Bindable
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
notifyPropertyChanged(BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
notifyPropertyChanged(BR.lastName);
}
}


@Bindable注解的getter方法对应的属性会在BR(类似R文件)生成一个标识,在数据改变时,调用notifyPropertyChanged方法可以对指定的Model属性数据更新进行通知,View收到通知后更新绑定的数据。
ac1e

(2)使用ObservableField

上面的方法略为繁琐,需要我们手动调用方法去通知view更新。因此,框架为我们做了进一步封装,提供了ObservableField、ObservableXxx(Xxx为基本数据类型)、ObservableParcelable等封装类。这些类都直接或者间接继承自BaseObservable,提供get()和set()方法,在set()方法中直接调用了notifyChange()方法通知View更新。

/**
* @return the stored value.
*/
public T get() {
return mValue;
}

/**
* Set the stored value.
*/
public void set(T value) {
if (value != mValue) {
mValue = value;
notifyChange();  // notify
}
}


使用方式:

public class User {
public final ObservableField<String> firstName = new ObservableField<>();
public final ObservableInt age = new ObservableInt();
}

User user = new User();
user.firstName.set("Harden");
user.age.set(25);


另外,对于集合类型,Data Binding框架提供了ObservableArrayList、ObservableArrayMap等封装,基本都是在集合的数据操作中,加入了框架的notify机制。

官方教程:https://developer.android.com/tools/data-binding/guide.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android