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
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories