Android 架构番外篇一:Data Binding基本用法

一、前言

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的内部原理

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容