Android DataBinding

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收到通知后更新绑定的数据。
(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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值