此篇博客参考 csdn小瓯
DataBinding是一种工具,能在编译时绑定布局和对象。通过这篇文章,一是要掌握DataBinding的使用,二是我们要弄懂,View层是怎么改变Model的,而Model层又是如何改变View的。
介绍
DataBinding是谷歌15年推出的library。DataBinding支持双向绑定,能大大减少绑定app逻辑与layout文件的“胶水代码”,例如setText、findViewById等代码。双向绑定,指的是将数据与界面绑定起来,当数据发生变化时会体现在界面上,反过来界面内容变化也会同步更新到数据上,使用DataBinding能轻松实现MVVM模式。
DataBinding生成的代码介绍
在分析双向绑定的原理之前,先了解DataBinding生成的主要代码,有activity_xxx.xml、activity_xxx-layout.xml、ActivityXxxBinding.java、ActivityXxxBindingImpl.java、BR.java、两个DataBinderMapperImpl.java等等。
APT预编译
我们已经知道,DataBinding里面的功能类是通过APT的工具来产生的。
APT(Annotation Processing Tool)即注解处理器,是一种处理注解的工具,确切的说它是javac的一个工具,它用来在编译时扫描和处理注解。注解处理器以Java代码(或者编译过的字节码)作为输入,生成.java文件作为输出。简单来说就是在编译期,通过注解生成.java文件。
当你的xml用DataBinding规定的格式去书写的时候,DataBinding就能够通过APT的技术,帮你生成对应的类文件。
Rebuild完成后,会在build目录下生成以 [布局名]Binding.java 文件,这里我们的布局叫activity_main,所以生成了一个名为ActivityMainBinding.Java类文件,以及继承自它的ActivityMainBindingImpl.java类文件。
生成文件的具体位置参考下图
布局的格式和处理
我们需要规定的格式来定义我们的xml布局文件,参考布局activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- DataBinding编码规范 -->
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 定义该View(布局)需要绑定的数据来源 -->
<data>
<variable
name="user"
type="pers.owen.databinding.model.UserInfo" />
</data>
<!-- 布局常规编码 -->
<LinearLayout...>
<EditText ... />
<EditText ... />
</LinearLayout>
</layout>
<data>
标签中绑定的可以是一个实体类,也可以是一个ViewModel,只要按照规定的格式去写,就可以。
在编译时,DataBinding会内部处理布局文件控件,重新生成两个全新的布局文件。一个与原文件同名,叫activity_main.xml
,另一个是名为activity_main-layout.xml
。
生成文件的具体位置参考下图
生成后的activity_main.xml就跟我们普通的xml文件一样,用于Android os的渲染。但是DataBinding会在每个控件上都加上Tag,这个Tag就是用来快速查找和定位具体控件的。
生成后的activity_main.xml代码如下
<?xml version="1.0" encoding="utf-8"?>
<!-- DataBinding编码规范 -->
<!-- 定义该View(布局)需要绑定的数据来源 -->
<!-- 布局常规编码 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" android:tag="layout/activity_main_0" xmlns:android="http://schemas.android.com/apk/res/android">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="binding_1" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:tag="binding_2" />
</LinearLayout>
生成的activity_main-layout.xml文件,是DataBinding生成的配置文件,它能够通过文件中的配置信息,快速定位哪一个控件,该显示什么信息。
可以看出,activity_main.xml与不用DataBinding前的布局文件差不多,唯一的区别是加了tag标记。 根布局的tag为layout/activity_main_0
,而button的tag为binding_0。那我们使用DataBinding时的data标签以及里面的import与variable标签在哪里?其实它们都在下面介绍得activity_main-layout.xml里面。使用DataBinding重写后的布局文件无法被“理解”,因此需要经过DataBinding处理成正常的布局文件activity_main.xml与包含绑定信息的文件activity_main-layout.xml
。
activity_main-layout.xml代码如下
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Layout directory="layout" filePath="C:\workspace\adrproject\MyDataBinding\app\src\main\res\layout\activity_main.xml"
isBindingData="true"
isMerge="false" layout="activity_main" modulePackage="pers.owen.databinding"
rootNodeType="android.widget.LinearLayout">
<Variables name="user" declared="true" type="pers.owen.databinding.model.UserInfo">
<location endLine="7" endOffset="57" startLine="5" startOffset="8" />
</Variables>
<Targets>
<Target tag="layout/activity_main_0" view="LinearLayout">
<Expressions />
<location endLine="27" endOffset="18" startLine="11" startOffset="4" />
</Target>
<Target tag="binding_1" view="EditText">
<Expressions>
<Expression attribute="android:text" text="user.name">
<Location endLine="20" endOffset="39" startLine="20" startOffset="12" />
<TwoWay>true</TwoWay>
<ValueLocation endLine="20" endOffset="37" startLine="20" startOffset="29" />
</Expression>
</Expressions>
<location endLine="20" endOffset="42" startLine="17" startOffset="8" />
</Target>
<Target tag="binding_2" view="EditText">
<Expressions>
<Expression attribute="android:text" text="user.pwd">
<Location endLine="26" endOffset="38" startLine="26" startOffset="12" />
<TwoWay>true</TwoWay>
<ValueLocation endLine="26" endOffset=