DataBinding使用进阶

来源:互联网 发布:人人商城v2 数据字典 编辑:程序博客网 时间:2024/06/02 01:01

需要DataBinding环境配置等细节的请移步到:
DataBinding-开始使用:
http://blog.csdn.net/wang2963973852/article/details/70858527
想要了解DataBinding原理的请移步:
DataBinding原理解析:
http://blog.csdn.net/wang2963973852/article/details/70858508

android原生支持MVVM-DataBinding

从2015年开始Android官方支持MVVM框架
首先我们需要知道MVVM是什么?
MVVM是从一种开发模式,不同于MVC和MVP,MVVM分为Model层、View层、和ViewModel层,MVVM最大的特点就是Model层和ViewModel层之间可以进行绑定,也就是说View可以对应着ViewModel

Google使用DataBinding来支持MVVM模型
Data Binding 解决了 Android UI 编程中的一个痛点,官方原生支持 MVVM 模型可以让我们在不改变既有代码框架的前提下,非常容易地使用这些新特性

使用DataBinding进行MVVM开发
DataBinding是2015年谷歌I/O上提出来的,从字面意思上看就是数据绑定,实际上就是将数据绑定在xml中,并实现及时刷新,听起来就碉堡了,再也没有了findviewbyId,虽然现在很多注解框架也能实现无findviewbyId,但是这样会影响性能,现在使用DataBinding就不需要这方面的考虑了

DataBinding技术能解决什么问题?

从开发角度看,简言之,DataBinding主要解决了两个问题:

1、需要多次使用findViewById,损害了应用性能且令人厌烦
2、更新UI数据需切换至UI线程,将数据分解映射到各个view比较麻烦

但是应该说:针对上述问题,都有第三方解决方案。第一个问题可以使用ButterKnife;对于第二个问题,谷歌提供了Loop-Handler方案,你还可以使用RxJava,EventBus等方案,但它们只是解决了线程切换的问题,却没有解决将数据分解映射到各个view的问题,这正是DataBinding的魅力所在!同时,DataBinding的线程切换也是透明的,这是指,当你的Activity需要展示新的数据时,你可以在后台线程中获取数据,然后直接交给DataBinding就可以了,完全不需要关心线程切换的问题。

DataBinding的使用规则:
使用 Data Binding 之后,xml的布局文件就不再单纯地展示 UI 元素,还需要定义 UI 元素用到的变量。所以,它的根节点不再是一个 ViewGroup,而是变成了 layout,并且新增了一个节点 data。

意思就是之前我们的布局文件就仅仅只是负责View的显示样式,一般来说不会涉及到任何和数据有关的东西,也就是说我们只会知道这个布局没有数据的时候回事什么样子的,但是加什么数据以及加上数据之后是什么样子我们完全不知道

<layout xmlns:android="http://schemas.android.com/apk/res/android"><data>    `... </data><!--原先的根节点(Root Element)--><LinearLayout> ....</LinearLayout></layout>

要实现 MVVM 的 ViewModel 就需要把数据与UI进行绑定,data 节点就为此提供了一个桥梁,我们先在 data 中声明一个 variable,这个变量会为 UI 元素提供数据(例如 TextView 的 android:text),然后在 Java 代码中把”后台”数据与这个 variable 进行绑定

我们知道在之前我们的布局文件中是不存在变量这个概念的,或者说我们的布局文件处理去获得Res资源文件中的数据之外是不可能主动获取数据的(除非在java代码中使用findViewById得到组件之后进行设置),而现在我们的布局不仅仅只是view了,而且还可以规定我们的view需要的数据,可以这样理解我们把布局文件进行了封装(类似接口),下载我们在布局中可以规定我们将会使用到的数据,

方法就是在根节点下面使用节点,声明一个变量,这里的type是用来定义这个变量的类型的,其作用就和你在java代码中使用 User xiaoming ;一样相当于是声明这个变量是什么类型的(当然名字这么长是因为使用过了自定义类的全类名),其中type属性就是我们在java文件中定义的数据bean类,如下:

<data><variable name="user" type="com.liangfeizc.databindingsamples.basic.User" /></data>

当然我们也是可以类似java类里面一样使用导入的方式来缩短type的写法

<data> <import type="com.liangfeizc.databindingsamples.basic.User" /><variable name="user" type="User" /></data>

然后因为我们在 build.gradle 中设置了databinding = true,所以DataBinding会根据xml文件的名称 Generate 一个继承自 ViewDataBinding 的类。(怪不得是需要Google官方支持的,原来是以插件的形式,具体来说应该是gradle支持的)

例如,这里 xml 的文件名叫 activity_basic.xml,那么生成的类就是 ActivityBasicBinding

java.lang.* 包中的类会被自动导入,可以直接使用,例如要定义一个 String 类型的变量:(type不需要写全类名,但是其他类型的还是需要写全类名的)

<variable name="firstName" type="String" />

layout文件绑定 Variable

修改 BasicActivity 的 onCreate 方法,用 DatabindingUtil. setContentView()来替换掉 setContentView(),此方法会返回一个ActivityBasicBinding对象,此对象就是你在layout文件中定义了之后DataBinding自动生成的,然后创建一个 user 对象,通过 binding.setUser(user) 与 variable 进行绑定(上一篇:DataBinding-开始使用 中介绍过为什么需要这么做)
http://blog.csdn.net/wang2963973852/article/details/70858527
(厉害了如果不是官方的,谁能这么深入android的源码,搞出这样的东西?这个MVVM已经不向MVP一样仅仅只是一种编程思想了,已经升级到了一种工具和一种框架的层面了)

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);ActivityBasicBinding binding = DataBindingUtil.setContentView(            this, R.layout.activity_basic);             User user = new User("fei", "Liang");         binding.setUser(user);

注意:
需要注意的是DataBinding会根据布局文件来生成一个类,这个类的类名是根据你的布局文件的名字自动生成的,但是点击这个自动生成的类写的时候,却直接进入了我们设置的布局文件,这更说明了这个自动生成的类是根据这个布局文件生成的,但是我们还是想去这个类看看怎么办:在这里:把工程切换到project类型,ActivityxxxBinding在/app/build/intermediates/classes/debug/xxx/xxx/xxx/databinding下,注意如果找不到那是因为这是在编译的时候生成的,因此需要debug一下

注意:
上面的ActivityBasicBinding 类是自动生成的,所有的 set 方法也是根据 variable 名称生成的。例如,我们定义了两个变量

<data>    <variable name="firstName" type="String" />    <variable name="lastName" type="String" /></data>

那么就会在ActivityBasicBinding 类中对应的生成两个方法,

setFirstName(String firstName);setLastName(String lastName);

为什么会生成上面两个方法,因为我们的ActivityBasicBinding 类是ViewModel,它不但持有view的引用而且持有model的引用,也就是说ActivityBasicBinding 里面不但有我们布局文件里面所有的组件的引用(解决了findViewById),而且有我们在layout中定义的变量的引用,这些引用都是以field的形式存在的

到这里我们的布局文件就正式的和我们的activity绑定了,而且我们在布局文件的《data》节点下定义的变量Variable也和我们对应的java数据bean类对象绑定了,

layout文件中使用 Variable

数据与 Variable 绑定之后,xml 的 UI 元素就可以直接使用了,如下:

<TextView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="@{user.lastName}" />

上面我们在布局文件中的一个textView里面使用了我们在此布局文件中定义的lastName变量,这个变量的类型是String类型
至此,一个简单的数据绑定就完成了

高级用法:(在XML文件中调用类方法)

首先假设我们在一个类里面定义了一个静态方法,如下:

 public class MyStringUtils {    public static String capitalize(final String word) {        return String.valueOf(word.charAt(0))+ word.substring(1);         }

然后在XML文件的节点中导入:

<import type="com.liangfeizc.databindingsamples.utils.MyStringUtils" /><variable            name="StringUtils"            type="MyStringUtils"/>

使用起来和java语法一样:

<TextView    android:layout_height="wrap_content"    android:text="@{StringUtils.capitalize(user.firstName)}" />

如上:使用方法和调用java方法一样:就是使用类名调用方法并且传入参数,然后将方法返回值使用到text属性得值上面,

@{className.mothodName(mothodParam)

但是需要注意的是:
我们知道DataBinding是Android官方出的支持MVVM的框架,但是即便是这样Android也不可能因为要支持MVVM,就对之前定义的XML文件中的组件的属性的用法进行修改,那么就只有DataBinding去适应Android布局文件中组件属性的使用方式了

举个例子吧:就拿上面的《TextView》来说明,我们想要给TextView的text属性设置值,那么我们知道text属性需要的值是字符串,而我们的大括号里面的是DataBinding定义的表达式,DataBinding每次在读取Android组件的属性值的时候,需要去解析大括号里面的表达式,然后将解析出来的值赋值给Android组件的属性,也就是说我们我们使用表达式调用的方法的返回值一定要是组件属性需要的类型

0 0
原创粉丝点击