一、前言
Data Binding自从公布到至今,也有一段时间了。从最初的Beta到如今比較完好的版本,能够说Data Binding已经是一个可用度非常高,也能带来实际生产力提升的技术了。
于是,我也迫不急待地想要把该技术运用到我的项目里面去了。
二、简介
什么是Data Binding
Data Binding。顾名去思义,数据绑定。是Google对MVVM在Android上的一种实现。能够直接绑定数据到xml中。并实现自己主动刷新。
DataBinding 库是 Google 公司 Android Framework UI 工具团队开发出来的一款 Android 库。它增强了 Android 项目中的布局文件对 UI 的控制能力,以前对 UI 进行控制和响应 UI 发出的命令的代码逻辑,现在就可以直接放在布局文件中使用 DataBinding 表达式 来表达,和 Java 代码中的数据直接关联。
通过这种声明式编程,可以大大减少 UI 和 逻辑代码之间的“胶水代码”,比如以前 Activity/Fragment 中的 UI 控制逻辑;从而增加了 layout xml 文件的表现力,当然也增加了 layout xml 文件的复杂程度,控制好 layout xml 文件中 bingding 表达式的复杂程度,把所有业务逻辑仍然放在 java 代码中,是使用好 DataBinding 库的关键。负责动画控制的逻辑建议仍然放在 java 代码中。
简单一句话,DataBinding 让你可以在布局文件中写 java 表达式,所以可以省略掉中间层。可以说 DataBinding 库是减少甚至完全代替 view 和 业务逻辑 之间中间层 stupid code 的利器。
优势
- 去掉Activities & Fragments内的大部分UI代码(setOnClickListener, setText, findViewById, etc.)
- XML变成UI的唯一真实来源
- 降低定义view id的主要用途(数据绑定直接发生在xml)
- 绑定发生在编译时,性能超过手写代码
- 保证运行在主线程
劣势
增加了xml布局复杂程度
IDE支持还不那么完好(提示、表达式)
重构支持不好(xml中进行重构。java代码不会自己主动改动)
三、基础用法
1、构建环境
首先,我们需要在gradle构建文件里添加Data Binding配置,如下:
android {
······
······
······
// Data Binding
dataBinding {
enabled = true
}
}
Data Binding插件将会在你的项目内添加必需提供的以及编译配置依赖。
2、在项目中使用DataBinding
gradle构建好环境后,我们就可以在项目中使用DataBinding了,下面我们一步步地迈入DataBinding的奇幻世界。
我们这里是在就demo的基础上,进行DataBinding改造。
2.1、调整你的布局文件
首先,我们来调整一下布局文件,让他支持DataBinding。
先来了解一下DataBinding 布局文件的结构,它与以前的布局文件有点不同,它以一个 layout 标签作为根节点,里面包含一个 data 标签与 layout 标签。layout 标签的内容就是调整前的普通布局文件内容。
布局最外层添加 layout tag
在xml的最外层套上layout标签就可以,改动后就能够看到生成了该布局相应的*Binding类.
<layout>
// 原来的layout
</layout>
布局中data标签
在最外层添加起始根标签layout,接下来添加一个data标签,为引入我们的数据做准备。
<layout>
<data>
…
</data>
// 原来的layout
</layout>
Binding文件生成规则
默认生成规则:通过xml文件名称,使用 下划线切割+驼峰式+Binding后缀 的命名规则生成Binding文件。
如:activity_main_layout.xml,则会生成ActivityMainLayoutBinding。
view对象的生成规则相似,仅仅是由于是类变量,首字母不是大写。比方有一个TextView的id是first_name,则会生成名为firstName的TextView。
另外,class name 也可以自定义,仅仅须要在data标签开始部分添加 class=“class name”即可:
<data class=“MyClassName”>
…
</data>
这样生成的类就会变成MyClassName。
注意: XML 还没有同步支持自定义class name ,会有错误提示,不过,不影响项目编译、运行及打包。
引入数据
上面添加了data标签,我们可以在其内部添加variable标签,以便引入数据,方式如下:
<data>
<variable
name="music"
type="com.yangbo.module_databinding.model.Music" />
</data>
使用数据
上一步,我们在data内描述了一个名为music的变量属性,使其可以在这个layout中使用,使用方法@{music.属性},调整后的布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="music"
type="com.yangbo.module_databinding.model.Music" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DataBMainActivity">
<TextView
android:id="@+id/album"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="@{music.mAlbum}" />
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@+id/album"
android:text="@{music.mName}" />
<TextView
android:id="@+id/singer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@+id/name"
android:text="@{music.mSinger}" />
……
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
以上,我们把布局文件调整完毕,接下调整我们的java文件,已达到使用DataBinding的目的。
2.2、调整JAVA文件
上面已经在布局里引入并且使用了数据,如果要生效,我们的Java文件也必须要做相应的调整。
调整model
将数据对象改造成data binding支持的方式,如,我们的model原来的实现:
public class Music {
private String mCover;
private String mAlbum;
private String mName;
private String mSinger;
public String getmCover() {
return mCover;
}
public String getmAlbum() {
return mAlbum;
}
public String getmName() {
return mName;
}
public String getmSinger() {
return mSinger;
}
public void setmCover(String mCover) {
this.mCover = mCover;
}
public void setmAlbum(String mAlbum) {
this.mAlbum = mAlbum;
}
public void setmName(String mName) {
this.mName = mName;
}
public void setmSinger(String mSinger) {
this.mSinger = mSinger;
}
}
改造步骤如下:
- 1、Music需要继承BaseObservable
- 2、私有属性公开
- 3、geter添加注解@Bindable,
- 4、seter添加属性更新通知notifyPropertyChanged(BR.ID)
最终改造成:
public class Music extends BaseObservable {
public String mCover;
public String mAlbum;
public String mName;
public String mSinger;
@Bindable
public String getmCover() {
return mCover;
}
@Bindable
public String getmAlbum() {
return mAlbum;
}
@Bindable
public String getmName() {
return mName;
}
@Bindable
public String getmSinger() {
return mSinger;
}
public void setmCover(String mCover) {
this.mCover = mCover;
notifyPropertyChanged(BR.mCover);
}
public void setmAlbum(String mAlbum) {
this.mAlbum = mAlbum;
notifyPropertyChanged(BR.mAlbum);
}
public void setmName(String mName) {
this.mName = mName;
notifyPropertyChanged(BR.mName);
}
public void setmSinger(String mSinger) {
this.mSinger = mSinger;
notifyPropertyChanged(BR.mSinger);
}
}
编译时,会根据数据类和类内添加的注解在 BR 类内生成一个元素,而 BR 类会生成在 module 的 package 下,如我们这里会生成:
package com.yangbo.module_databinding;
public class BR {
public static final int _all = 0;
public static final int music = 1;
public static final int mAlbum = 2;
public static final int mName = 3;
public static final int mSinger = 4;
public static final int mCover = 5;
}
生成Binding实例
全部Binding实例的生成都能够通过DataBindingUtil进行,方法名与该view的原inflate方法一致。如activity仍然为setContentView,仅仅是添加了參数由于须要获得activity。
setContentView(R.layout.databinding_activity_layout);
改造成:
DatabindingActivityLayoutBinding mDatabing = DataBindingUtil.setContentView(this,
R.layout.databinding_activity_layout);
去除findViewById
使用了Data Binding后,我们再也不须要findViewById,由于一切有id的view,都已经在Binding类中被初始化完毕了,仅仅须要直接通过binding实例訪问就可以。
BottomNavigationView navView = findViewById(R.id.nav_view);
mTextMessage = findViewById(R.id.message);
改造成
mTextMessage = mDatabing.message;
BottomNavigationView navView = mDatabing.navView;
设置数据
music = new Music();
String coverUri = "https://timgsa.baidu.com/timg?image&quality=80&size=b10000_10000&sec=1556696004&di=3fdd27a43aa97488b7cec87074819c1b&src=http://wx4.sinaimg.cn/mw690/bec62f35gy1fhfzh6ri3qj20m80veq5h.jpg";
music.setmCover(coverUri);
music.setmAlbum("江南");
music.setmName("江南");
music.setmSinger("林俊杰");
mDatabing.setMusic(music);
// 或者直接通过setVariable
mDatabing.setVariable(BR.music, music);
以上,我们就完成了一个小demo对Databinding的改造,接下来编译并且运行,如无意外,程序跑起来好,直接就能看到你预期的效果了。
四、结语
好了,经过上面介绍,我们已经掌握了Data Binding的基本使用方法。Data Binding可以说是大大的减少了我们的一些无关要紧的代码,从而减少了总体的代码量。
希望通过本文初步了解Data Binding,让你对它产生兴趣,并且在你的项目里也用起来。
当然,DataBinding能做的事情非常多,计划下一节详细介绍一下DataBinding的详细使用。
另外,我想应该有不少童鞋,和我有一样的想法,就是Data Binding是怎么做到数据绑定自动刷新的,这个就涉及到Data Binding的原理及实现,我计划再来一节,讲述Data Binding的内部原理。