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

完全掌握Android Data Binding

2016-04-18 11:30 363 查看
来源 https://github.com/LyndonChin/MasteringAndroidDataBinding

编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识、前端、后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过!

本教程是跟着 Data Binding Guide 学习过程中得出的一些实践经验,同时修改了官方教程的一些错误,每一个知识点都有对应的源码,争取做到实践与理论相结合。

Data Binding 解决了 Android UI 编程中的一个痛点,官方原生支持 MVVM 模型可以让我们在不改变既有代码框架的前提下,非常容易地使用这些新特性。其实在此之前,已经有些第三方的框架(RoboAndroid)
可以支持 MVVM 模型,无耐由于框架的侵入性太强,导致一直没有流行起来。


准备


Android Studio 更新到 1.3 版本

打开 Preferences,找到 Appearances & Behavior 下的 Updates 选项,把 Automatically Check updates for 修改成 Canary
Channel。



注意

Data Binding 是一个 support 包,因此与 Android M 没什么关系,可以不用下载 Android MNC Preview 的 SDK。


新建一个 Project

修改 Project 的 build.gradle,为
build script 添加一条依赖,Gradle 版本为 1.2.3。

为用到 Data Binding 的模块添加插件,修改对应的 build.gradle

注意

如果 Module 用到的 buildToolsVersion 高于 22.0.1,比如 23 rc1,那
com.android.databinding:dataBinder
的版本要改为 1.3.0-beta1,否则会出现如下错误:




基础

工程创建完成后,我们通过一个最简单的例子来说明 Data Binding 的基本用法。


布局文件

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


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

如果要用一个表格来展示用户的基本信息,用 Data Binding 应该怎么实现呢?


数据对象

添加一个 POJO 类 -
User
,非常简单,四个属性以及他们的 getter 和 setter。

稍后,我们会新建一个
User
类型的变量,然后把它跟布局文件中声明的变量进行绑定。


定义 Variable

再回到布局文件,在
data
节点中声明一个变量
user


其中
type
属性就是我们在 Java 文件中定义的
User
类。

当然,
data
节点也支持
import
,所以上面的代码可以换一种形式来写。

然后我们刚才在 build.gradle 中添加的那个插件 -
com.android.databinding
会根据xml文件的名称 Generate 一个继承自
ViewDataBinding
的类。

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


注意

java.lang.*
包中的类会被自动导入,可以直接使用,例如要定义一个
String
类型的变量:


绑定 Variable

修改
BasicActivity
onCreate
方法,用
DatabindingUtil.setContentView()
来替换掉
setContentView()
,然后创建一个
user
对象,通过
binding.setUser(user)
variable
进行绑定。

注意

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

那么就会生成对应的两个 set 方法。


使用 Variable

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

至此,一个简单的数据绑定就完成了,可参考完整代码


高级用法


使用类方法

首先为类添加一个静态方法

然后在 xml 的
data
节点中导入:

使用方法与 Java 语法一样:


类型别名

如果我们在
data
节点了导入了两个同名的类怎么办?

这样一来出现了两个
User
类,那
user
变量要用哪一个呢?不用担心,
import
还有一个
alias
属性。


Null Coalescing 运算符

就等价于


属性值

通过
${}
可以直接把 Java 中定义的属性值赋值给 xml 属性。


使用资源数据

这个例子,官方教程有错误,可以参考Android Data Binder 的一个bug,完整代码在此


Observable Binding

本来这一节的标题应该叫双向绑定,但是很遗憾,现在的 Data Binding 暂时支持单向绑定,还没有达到 Angular.js 的威力。

要实现 Observable Binding,首先得有一个实现了 android.databinding.Observable 的类,为了方便,Android 原生提供了已经封装好的一个类 - BaseObservable,并且实现了监听器的注册机制。

我们可以直接继承 BaseObservable。

BR
是编译阶段生成的一个类,功能与
R.java
类似,用
@Bindable
标记过
getter
方法会在
BR
中生成一个 entry,当我们

通过代码可以看出,当数据发生变化时还是需要手动发出通知。 通过调用
notifyPropertyChanged(BR.firstName)
来通知系统
BR.firstName
这个
entry
的数据已经发生变化,需要更新
UI。

除此之外,还有一种更细粒度的绑定方式,可以具体到成员变量,这种方式无需继承
BaseObservable
,一个简单的 POJO就可以实现。

系统为我们提供了所有的 primitive type 所对应的 Observable类,例如
ObservableInt
ObservableFloat
ObservableBoolean
等等,还有一个
ObservableField
对应着 reference
type。

剩下的数据绑定与前面介绍的方式一样,具体可参考ObservableActivity


带 ID 的 View

Data Binding 有效降低了代码的冗余性,甚至完全没有必要再去获取一个 View 实例,但是情况不是绝对的,万一我们真的就需要了呢?不用担心,只要给 View 定义一个 ID,Data Binding 就会为我们生成一个对应的
final
变量。

上面代码中定义了一个 ID 为 firstName* 的
TextView
,那么它对应的变量就是

具体代码可参考 ViewWithIDsActivity.java


ViewStubs

xml中的
ViewStub
经过 binding 之后会转换成
ViewStubProxy
,
具体代码可参考 ViewStubActivity.java

简单用代码说明一下,xml 文件与之前的代码一样,根节点改为
layout
,在
LinearLayout
中添加一个
ViewStub
,添加ID。

在 Java 代码中获取
binding
实例,为
ViewStubProy
注册
ViewStub.OnInflateListener
事件,搞定!


Dynamic Variables

完整代码可以参考 dynamic

RecyclerView
为例,
Adapter
的 DataBinding 需要动态生成,因此我们可以在
onCreateViewHolder
的时候创建这个DataBinding,然后在
onBindViewHolder
中获取这个 DataBinding。

注意此处
DataBindingUtil
的用法:


Attribute setters

有了 Data Binding,即使属性没有在
declare-styleable
中定义,我们也可以通过
xml 进行赋值操作。 为了演示这个功能,我自定义了一个 View - UserView,其中 R.styleable.UserView 中只定义了一个
age
属性,其中
firstName
lastName
只有对应的两个
setter
方法。

只要有
setter
方法就可以这样为属性赋值:

onClickListener
也是同样道理,只不过我们是在
Activity
中定义了一个
Listener


转换器 (Converters)

具体代码可参考 ConversionsActivity.java

在 xml 中为属性赋值时,如果变量的类型与属性不一致,通过 DataBinding 可以进行转换。

只需要定义一个标记了
@BindingConversion
的静态方法即可:

至此,官网所介绍的用法都在代码中实践过了,如果你喜欢,请为我点赞 :)

我的微博

个人博客

twitter

facebook
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: